From d04f369d85c1fc4184bd29b62df9903507eca18a Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 18:15:32 +0200 Subject: [PATCH 01/69] search basic implementation --- client/adventureMap/AdventureMapShortcuts.cpp | 37 ++++++++++++++++++- client/adventureMap/AdventureMapShortcuts.h | 1 + client/gui/Shortcut.h | 1 + client/gui/ShortcutHandler.cpp | 1 + config/shortcutsConfig.json | 1 + 5 files changed, 40 insertions(+), 1 deletion(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index fe7253cb0..9497bf1df 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -36,6 +36,7 @@ #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapping/CMap.h" #include "../../lib/pathfinder/CGPathNode.h" +#include "../../lib/mapObjectConstructors/CObjectClassesHandler.h" AdventureMapShortcuts::AdventureMapShortcuts(AdventureMapInterface & owner) : owner(owner) @@ -109,7 +110,8 @@ std::vector AdventureMapShortcuts::getShortcuts() { EShortcut::ADVENTURE_MOVE_HERO_EE, optionHeroSelected(), [this]() { this->moveHeroDirectional({+1, 0}); } }, { EShortcut::ADVENTURE_MOVE_HERO_NW, optionHeroSelected(), [this]() { this->moveHeroDirectional({-1, -1}); } }, { EShortcut::ADVENTURE_MOVE_HERO_NN, optionHeroSelected(), [this]() { this->moveHeroDirectional({ 0, -1}); } }, - { EShortcut::ADVENTURE_MOVE_HERO_NE, optionHeroSelected(), [this]() { this->moveHeroDirectional({+1, -1}); } } + { EShortcut::ADVENTURE_MOVE_HERO_NE, optionHeroSelected(), [this]() { this->moveHeroDirectional({+1, -1}); } }, + { EShortcut::ADVENTURE_SEARCH, optionSidePanelActive(),[this]() { this->search(); } } }; return result; } @@ -457,6 +459,39 @@ void AdventureMapShortcuts::zoom( int distance) owner.hotkeyZoom(distance, false); } +void AdventureMapShortcuts::search() +{ + LOCPLINT->showInfoDialog("search"); + + std::vector visitableObjInstances; + int3 mapSizes = LOCPLINT->cb->getMapSize(); + for(int x = 0; x < mapSizes.x; x++) + for(int y = 0; y < mapSizes.y; y++) + for(int z = 0; z < mapSizes.z; z++) + for(auto & obj : LOCPLINT->cb->getVisitableObjs(int3(x, y, z), false)) + visitableObjInstances.push_back(obj->id); + + // count of elements for each group + std::map mapObjCount; + for(auto & obj : visitableObjInstances) + mapObjCount[LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex()]++; + + // sort by name + std::vector> mapObjCountList; + for (auto itr = mapObjCount.begin(); itr != mapObjCount.end(); ++itr) + mapObjCountList.push_back(*itr); + std::sort(mapObjCountList.begin(), mapObjCountList.end(), + [=](std::pair& a, std::pair& b) + { + return VLC->objtypeh->getObjectName(a.first, 0) < VLC->objtypeh->getObjectName(b.first, 0); + } + ); + + //TODO show table as popup + for(auto & obj : mapObjCountList) + std::cout << VLC->objtypeh->getObjectName(obj.first, 0) << " " << obj.second << "\n"; +} + void AdventureMapShortcuts::nextObject() { const CGHeroInstance *h = LOCPLINT->localState->getCurrentHero(); diff --git a/client/adventureMap/AdventureMapShortcuts.h b/client/adventureMap/AdventureMapShortcuts.h index b32f3ea29..cfe07b781 100644 --- a/client/adventureMap/AdventureMapShortcuts.h +++ b/client/adventureMap/AdventureMapShortcuts.h @@ -71,6 +71,7 @@ class AdventureMapShortcuts void nextTown(); void nextObject(); void zoom( int distance); + void search(); void moveHeroDirectional(const Point & direction); public: diff --git a/client/gui/Shortcut.h b/client/gui/Shortcut.h index 66019bd77..3bf0502d8 100644 --- a/client/gui/Shortcut.h +++ b/client/gui/Shortcut.h @@ -161,6 +161,7 @@ enum class EShortcut ADVENTURE_RESTART_GAME, ADVENTURE_TO_MAIN_MENU, ADVENTURE_QUIT_GAME, + ADVENTURE_SEARCH, // Move hero one tile in specified direction. Bound to cursors & numpad buttons ADVENTURE_MOVE_HERO_SW, diff --git a/client/gui/ShortcutHandler.cpp b/client/gui/ShortcutHandler.cpp index a4cffb8c4..e64d9350d 100644 --- a/client/gui/ShortcutHandler.cpp +++ b/client/gui/ShortcutHandler.cpp @@ -209,6 +209,7 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const {"adventureZoomIn", EShortcut::ADVENTURE_ZOOM_IN }, {"adventureZoomOut", EShortcut::ADVENTURE_ZOOM_OUT }, {"adventureZoomReset", EShortcut::ADVENTURE_ZOOM_RESET }, + {"adventureSearch", EShortcut::ADVENTURE_SEARCH }, {"battleToggleHeroesStats", EShortcut::BATTLE_TOGGLE_HEROES_STATS}, {"battleToggleQueue", EShortcut::BATTLE_TOGGLE_QUEUE }, {"battleUseCreatureSpell", EShortcut::BATTLE_USE_CREATURE_SPELL }, diff --git a/config/shortcutsConfig.json b/config/shortcutsConfig.json index 41ee66f22..111026765 100644 --- a/config/shortcutsConfig.json +++ b/config/shortcutsConfig.json @@ -56,6 +56,7 @@ "adventureZoomIn": "Keypad +", "adventureZoomOut": "Keypad -", "adventureZoomReset": "Backspace", + "adventureSearch": "Ctrl+F", "battleAutocombat": "A", "battleAutocombatEnd": "Q", "battleCastSpell": "C", From 5ea9063a3b5d6948e8c37c0448298e9d43d4fa73 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 19:47:10 +0200 Subject: [PATCH 02/69] search with CObjectListWindow --- Mods/vcmi/config/vcmi/english.json | 2 ++ Mods/vcmi/config/vcmi/german.json | 2 ++ client/adventureMap/AdventureMapShortcuts.cpp | 28 +++++++++++++++---- 3 files changed, 26 insertions(+), 6 deletions(-) diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index b62ee25d2..032f6ac2e 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -13,6 +13,8 @@ "vcmi.adventureMap.monsterThreat.levels.10" : "Deadly", "vcmi.adventureMap.monsterThreat.levels.11" : "Impossible", "vcmi.adventureMap.monsterLevel" : "\n\nLevel %LEVEL %TOWN unit", + "vcmi.adventureMap.search.hover" : "Search map object", + "vcmi.adventureMap.search.help" : "Select object to search on map.", "vcmi.adventureMap.confirmRestartGame" : "Are you sure you want to restart the game?", "vcmi.adventureMap.noTownWithMarket" : "There are no available marketplaces!", diff --git a/Mods/vcmi/config/vcmi/german.json b/Mods/vcmi/config/vcmi/german.json index efe786220..0ca8f9748 100644 --- a/Mods/vcmi/config/vcmi/german.json +++ b/Mods/vcmi/config/vcmi/german.json @@ -13,6 +13,8 @@ "vcmi.adventureMap.monsterThreat.levels.10" : "Tödlich", "vcmi.adventureMap.monsterThreat.levels.11" : "Unmöglich", "vcmi.adventureMap.monsterLevel" : "\n\nStufe %LEVEL %TOWN-Einheit", + "vcmi.adventureMap.search.hover" : "Suche Kartenobjekt", + "vcmi.adventureMap.search.help" : "Wähle Objekt das gesucht werden soll.", "vcmi.adventureMap.confirmRestartGame" : "Seid Ihr sicher, dass Ihr das Spiel neu starten wollt?", "vcmi.adventureMap.noTownWithMarket" : "Kein Marktplatz verfügbar!", diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index 9497bf1df..0980e6634 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -24,6 +24,7 @@ #include "../windows/CKingdomInterface.h" #include "../windows/CSpellWindow.h" #include "../windows/CMarketWindow.h" +#include "../windows/GUIClasses.h" #include "../windows/settings/SettingsMainWindow.h" #include "AdventureMapInterface.h" #include "AdventureOptions.h" @@ -461,8 +462,6 @@ void AdventureMapShortcuts::zoom( int distance) void AdventureMapShortcuts::search() { - LOCPLINT->showInfoDialog("search"); - std::vector visitableObjInstances; int3 mapSizes = LOCPLINT->cb->getMapSize(); for(int x = 0; x < mapSizes.x; x++) @@ -477,19 +476,36 @@ void AdventureMapShortcuts::search() mapObjCount[LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex()]++; // sort by name - std::vector> mapObjCountList; + std::vector> mapObjCountList; for (auto itr = mapObjCount.begin(); itr != mapObjCount.end(); ++itr) mapObjCountList.push_back(*itr); std::sort(mapObjCountList.begin(), mapObjCountList.end(), - [=](std::pair& a, std::pair& b) + [=](std::pair& a, std::pair& b) { return VLC->objtypeh->getObjectName(a.first, 0) < VLC->objtypeh->getObjectName(b.first, 0); } ); - //TODO show table as popup + std::vector texts; for(auto & obj : mapObjCountList) - std::cout << VLC->objtypeh->getObjectName(obj.first, 0) << " " << obj.second << "\n"; + texts.push_back(VLC->objtypeh->getObjectName(obj.first, 0) + " (" + std::to_string(obj.second) + ")"); + + GH.windows().createAndPushWindow(texts, nullptr, + CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), + CGI->generaltexth->translate("vcmi.adventureMap.search.help"), + [this, mapObjCountList, visitableObjInstances](int index) + { + auto selObj = mapObjCountList[index].first; + for(auto & obj : visitableObjInstances) + { + auto objInst = LOCPLINT->cb->getObjInstance(obj); + if(selObj == objInst->getObjGroupIndex()) + owner.centerOnObject(objInst); + } + + + }, + 0); } void AdventureMapShortcuts::nextObject() From bd58caac132fc3bda66e2555ab040d424bd6b548 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 20:20:19 +0200 Subject: [PATCH 03/69] search feature working --- client/adventureMap/AdventureMapShortcuts.cpp | 44 ++++++++++++------- client/adventureMap/AdventureMapShortcuts.h | 5 +++ 2 files changed, 34 insertions(+), 15 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index 0980e6634..e4b4b3284 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -43,6 +43,8 @@ AdventureMapShortcuts::AdventureMapShortcuts(AdventureMapInterface & owner) : owner(owner) , state(EAdventureState::NOT_INITIALIZED) , mapLevel(0) + , searchLast(MapObjectID::NO_OBJ) + , searchPos(0) {} void AdventureMapShortcuts::setState(EAdventureState newState) @@ -462,6 +464,7 @@ void AdventureMapShortcuts::zoom( int distance) void AdventureMapShortcuts::search() { + // get all relevant objects std::vector visitableObjInstances; int3 mapSizes = LOCPLINT->cb->getMapSize(); for(int x = 0; x < mapSizes.x; x++) @@ -486,26 +489,37 @@ void AdventureMapShortcuts::search() } ); + // get pos of last selection + int lastSel = 0; + for(int i = 0; i < mapObjCountList.size(); i++) + if(mapObjCountList[i].first == searchLast) + lastSel = i; + + // create texts std::vector texts; for(auto & obj : mapObjCountList) texts.push_back(VLC->objtypeh->getObjectName(obj.first, 0) + " (" + std::to_string(obj.second) + ")"); - GH.windows().createAndPushWindow(texts, nullptr, - CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), - CGI->generaltexth->translate("vcmi.adventureMap.search.help"), - [this, mapObjCountList, visitableObjInstances](int index) - { - auto selObj = mapObjCountList[index].first; - for(auto & obj : visitableObjInstances) - { - auto objInst = LOCPLINT->cb->getObjInstance(obj); - if(selObj == objInst->getObjGroupIndex()) - owner.centerOnObject(objInst); - } - + GH.windows().createAndPushWindow(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), + [this, mapObjCountList, visitableObjInstances](int index) + { + auto selObj = mapObjCountList[index].first; - }, - 0); + // filter for matching objects + std::vector selVisitableObjInstances; + for(auto & obj : visitableObjInstances) + if(selObj == LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex()) + selVisitableObjInstances.push_back(obj); + + if(searchPos + 1 < selVisitableObjInstances.size() && searchLast == selObj) + searchPos++; + else + searchPos = 0; + + auto objInst = LOCPLINT->cb->getObjInstance(selVisitableObjInstances[searchPos]); + owner.centerOnObject(objInst); + searchLast = objInst->getObjGroupIndex(); + }, lastSel); } void AdventureMapShortcuts::nextObject() diff --git a/client/adventureMap/AdventureMapShortcuts.h b/client/adventureMap/AdventureMapShortcuts.h index cfe07b781..e0c8146b1 100644 --- a/client/adventureMap/AdventureMapShortcuts.h +++ b/client/adventureMap/AdventureMapShortcuts.h @@ -10,6 +10,8 @@ #pragma once +#include "../../lib/constants/EntityIdentifiers.h" + VCMI_LIB_NAMESPACE_BEGIN class Point; class Rect; @@ -33,6 +35,9 @@ class AdventureMapShortcuts EAdventureState state; int mapLevel; + MapObjectID searchLast; + int searchPos; + void showOverview(); void worldViewBack(); void worldViewScale1x(); From e85e938865e97d6f3e4df3590b33ee2ea48ec73b Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 20:44:08 +0200 Subject: [PATCH 04/69] use subid --- client/adventureMap/AdventureMapShortcuts.cpp | 21 ++++++++++--------- client/adventureMap/AdventureMapShortcuts.h | 2 +- .../CObjectClassesHandler.cpp | 2 +- 3 files changed, 13 insertions(+), 12 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index e4b4b3284..42eabc096 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -43,7 +43,7 @@ AdventureMapShortcuts::AdventureMapShortcuts(AdventureMapInterface & owner) : owner(owner) , state(EAdventureState::NOT_INITIALIZED) , mapLevel(0) - , searchLast(MapObjectID::NO_OBJ) + , searchLast({MapObjectID::NO_OBJ, 0}) , searchPos(0) {} @@ -471,21 +471,22 @@ void AdventureMapShortcuts::search() for(int y = 0; y < mapSizes.y; y++) for(int z = 0; z < mapSizes.z; z++) for(auto & obj : LOCPLINT->cb->getVisitableObjs(int3(x, y, z), false)) - visitableObjInstances.push_back(obj->id); + if(obj->ID != MapObjectID::MONSTER && obj->ID != MapObjectID::EVENT && obj->ID != MapObjectID::HERO) + visitableObjInstances.push_back(obj->id); // count of elements for each group - std::map mapObjCount; + std::map, int> mapObjCount; for(auto & obj : visitableObjInstances) - mapObjCount[LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex()]++; + mapObjCount[{ LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex() }]++; // sort by name - std::vector> mapObjCountList; + std::vector, int>> mapObjCountList; for (auto itr = mapObjCount.begin(); itr != mapObjCount.end(); ++itr) mapObjCountList.push_back(*itr); std::sort(mapObjCountList.begin(), mapObjCountList.end(), - [=](std::pair& a, std::pair& b) + [=](std::pair, int>& a, std::pair, int>& b) { - return VLC->objtypeh->getObjectName(a.first, 0) < VLC->objtypeh->getObjectName(b.first, 0); + return VLC->objtypeh->getObjectName(a.first.first, a.first.second) < VLC->objtypeh->getObjectName(b.first.first, b.first.second); } ); @@ -498,7 +499,7 @@ void AdventureMapShortcuts::search() // create texts std::vector texts; for(auto & obj : mapObjCountList) - texts.push_back(VLC->objtypeh->getObjectName(obj.first, 0) + " (" + std::to_string(obj.second) + ")"); + texts.push_back(VLC->objtypeh->getObjectName(obj.first.first, obj.first.second) + " (" + std::to_string(obj.second) + ")"); GH.windows().createAndPushWindow(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), [this, mapObjCountList, visitableObjInstances](int index) @@ -508,7 +509,7 @@ void AdventureMapShortcuts::search() // filter for matching objects std::vector selVisitableObjInstances; for(auto & obj : visitableObjInstances) - if(selObj == LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex()) + if(selObj == std::pair{ LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex() }) selVisitableObjInstances.push_back(obj); if(searchPos + 1 < selVisitableObjInstances.size() && searchLast == selObj) @@ -518,7 +519,7 @@ void AdventureMapShortcuts::search() auto objInst = LOCPLINT->cb->getObjInstance(selVisitableObjInstances[searchPos]); owner.centerOnObject(objInst); - searchLast = objInst->getObjGroupIndex(); + searchLast = { objInst->getObjGroupIndex(), objInst->getObjTypeIndex() }; }, lastSel); } diff --git a/client/adventureMap/AdventureMapShortcuts.h b/client/adventureMap/AdventureMapShortcuts.h index e0c8146b1..6e3a03572 100644 --- a/client/adventureMap/AdventureMapShortcuts.h +++ b/client/adventureMap/AdventureMapShortcuts.h @@ -35,7 +35,7 @@ class AdventureMapShortcuts EAdventureState state; int mapLevel; - MapObjectID searchLast; + std::pair searchLast; int searchPos; void showOverview(); diff --git a/lib/mapObjectConstructors/CObjectClassesHandler.cpp b/lib/mapObjectConstructors/CObjectClassesHandler.cpp index e45332abb..2ba61627c 100644 --- a/lib/mapObjectConstructors/CObjectClassesHandler.cpp +++ b/lib/mapObjectConstructors/CObjectClassesHandler.cpp @@ -353,7 +353,7 @@ TObjectTypeHandler CObjectClassesHandler::getHandlerFor(MapObjectID type, MapObj return mapObjectTypes.front()->objectTypeHandlers.front(); auto subID = subtype.getNum(); - if (type == Obj::PRISON || type == Obj::HERO_PLACEHOLDER) + if (type == Obj::PRISON || type == Obj::HERO_PLACEHOLDER || type == Obj::SPELL_SCROLL) subID = 0; auto result = mapObjectTypes.at(type.getNum())->objectTypeHandlers.at(subID); From 07aa7bac3c787c3258818c641fc85eba59ab6b25 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 21:19:42 +0200 Subject: [PATCH 05/69] search for texts --- client/adventureMap/AdventureMapShortcuts.cpp | 32 +++++++++---------- client/adventureMap/AdventureMapShortcuts.h | 2 +- client/widgets/ObjectLists.cpp | 3 ++ client/windows/GUIClasses.cpp | 2 ++ 4 files changed, 22 insertions(+), 17 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index 42eabc096..01347f453 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -43,7 +43,7 @@ AdventureMapShortcuts::AdventureMapShortcuts(AdventureMapInterface & owner) : owner(owner) , state(EAdventureState::NOT_INITIALIZED) , mapLevel(0) - , searchLast({MapObjectID::NO_OBJ, 0}) + , searchLast("") , searchPos(0) {} @@ -475,41 +475,41 @@ void AdventureMapShortcuts::search() visitableObjInstances.push_back(obj->id); // count of elements for each group - std::map, int> mapObjCount; + std::map mapObjCount; for(auto & obj : visitableObjInstances) - mapObjCount[{ LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex() }]++; + mapObjCount[{ VLC->objtypeh->getObjectName(LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex()) }]++; // sort by name - std::vector, int>> mapObjCountList; + std::vector> textCountList; for (auto itr = mapObjCount.begin(); itr != mapObjCount.end(); ++itr) - mapObjCountList.push_back(*itr); - std::sort(mapObjCountList.begin(), mapObjCountList.end(), - [=](std::pair, int>& a, std::pair, int>& b) + textCountList.push_back(*itr); + std::sort(textCountList.begin(), textCountList.end(), + [=](std::pair& a, std::pair& b) { - return VLC->objtypeh->getObjectName(a.first.first, a.first.second) < VLC->objtypeh->getObjectName(b.first.first, b.first.second); + return a.first < b.first; } ); // get pos of last selection int lastSel = 0; - for(int i = 0; i < mapObjCountList.size(); i++) - if(mapObjCountList[i].first == searchLast) + for(int i = 0; i < textCountList.size(); i++) + if(textCountList[i].first == searchLast) lastSel = i; // create texts std::vector texts; - for(auto & obj : mapObjCountList) - texts.push_back(VLC->objtypeh->getObjectName(obj.first.first, obj.first.second) + " (" + std::to_string(obj.second) + ")"); + for(auto & obj : textCountList) + texts.push_back(obj.first + " (" + std::to_string(obj.second) + ")"); GH.windows().createAndPushWindow(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), - [this, mapObjCountList, visitableObjInstances](int index) + [this, textCountList, visitableObjInstances](int index) { - auto selObj = mapObjCountList[index].first; + auto selObj = textCountList[index].first; // filter for matching objects std::vector selVisitableObjInstances; for(auto & obj : visitableObjInstances) - if(selObj == std::pair{ LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex() }) + if(selObj == VLC->objtypeh->getObjectName(LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex())) selVisitableObjInstances.push_back(obj); if(searchPos + 1 < selVisitableObjInstances.size() && searchLast == selObj) @@ -519,7 +519,7 @@ void AdventureMapShortcuts::search() auto objInst = LOCPLINT->cb->getObjInstance(selVisitableObjInstances[searchPos]); owner.centerOnObject(objInst); - searchLast = { objInst->getObjGroupIndex(), objInst->getObjTypeIndex() }; + searchLast = VLC->objtypeh->getObjectName(objInst->getObjGroupIndex(), objInst->getObjTypeIndex()); }, lastSel); } diff --git a/client/adventureMap/AdventureMapShortcuts.h b/client/adventureMap/AdventureMapShortcuts.h index 6e3a03572..7a5bff54d 100644 --- a/client/adventureMap/AdventureMapShortcuts.h +++ b/client/adventureMap/AdventureMapShortcuts.h @@ -35,7 +35,7 @@ class AdventureMapShortcuts EAdventureState state; int mapLevel; - std::pair searchLast; + std::string searchLast; int searchPos; void showOverview(); diff --git a/client/widgets/ObjectLists.cpp b/client/widgets/ObjectLists.cpp index d2ad5c1ae..d9a257923 100644 --- a/client/widgets/ObjectLists.cpp +++ b/client/widgets/ObjectLists.cpp @@ -185,6 +185,9 @@ void CListBox::scrollTo(size_t which) //scroll down else if (first + items.size() <= which && which < totalSize) moveToPos(which - items.size() + 1); + + if(slider) + slider->scrollTo(which); } void CListBox::moveToPos(size_t which) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 46a9775e5..9ab54fe39 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -1494,6 +1494,7 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, std::share } init(titleWidget_, _title, _descr); + list->scrollTo(initialSelection); } CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection, std::vector> images) @@ -1509,6 +1510,7 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, st items.push_back(std::make_pair(int(i), _items[i])); init(titleWidget_, _title, _descr); + list->scrollTo(initialSelection); } void CObjectListWindow::init(std::shared_ptr titleWidget_, std::string _title, std::string _descr) From e86b694b22fcab986b13ca28c5c8c47f3ccd365c Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 21:36:45 +0200 Subject: [PATCH 06/69] fast search --- client/adventureMap/AdventureMapShortcuts.cpp | 16 +++++++++++----- client/adventureMap/AdventureMapShortcuts.h | 2 +- client/gui/Shortcut.h | 1 + client/gui/ShortcutHandler.cpp | 1 + config/shortcutsConfig.json | 1 + 5 files changed, 15 insertions(+), 6 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index 01347f453..fce6ec5fe 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -114,7 +114,8 @@ std::vector AdventureMapShortcuts::getShortcuts() { EShortcut::ADVENTURE_MOVE_HERO_NW, optionHeroSelected(), [this]() { this->moveHeroDirectional({-1, -1}); } }, { EShortcut::ADVENTURE_MOVE_HERO_NN, optionHeroSelected(), [this]() { this->moveHeroDirectional({ 0, -1}); } }, { EShortcut::ADVENTURE_MOVE_HERO_NE, optionHeroSelected(), [this]() { this->moveHeroDirectional({+1, -1}); } }, - { EShortcut::ADVENTURE_SEARCH, optionSidePanelActive(),[this]() { this->search(); } } + { EShortcut::ADVENTURE_SEARCH, optionSidePanelActive(),[this]() { this->search(false); } }, + { EShortcut::ADVENTURE_SEARCH_CONTINUE, optionSidePanelActive(),[this]() { this->search(true); } } }; return result; } @@ -462,7 +463,7 @@ void AdventureMapShortcuts::zoom( int distance) owner.hotkeyZoom(distance, false); } -void AdventureMapShortcuts::search() +void AdventureMapShortcuts::search(bool next) { // get all relevant objects std::vector visitableObjInstances; @@ -501,8 +502,8 @@ void AdventureMapShortcuts::search() for(auto & obj : textCountList) texts.push_back(obj.first + " (" + std::to_string(obj.second) + ")"); - GH.windows().createAndPushWindow(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), - [this, textCountList, visitableObjInstances](int index) + // function to center element from list on map + auto selectObjOnMap = [this, textCountList, visitableObjInstances](int index) { auto selObj = textCountList[index].first; @@ -520,7 +521,12 @@ void AdventureMapShortcuts::search() auto objInst = LOCPLINT->cb->getObjInstance(selVisitableObjInstances[searchPos]); owner.centerOnObject(objInst); searchLast = VLC->objtypeh->getObjectName(objInst->getObjGroupIndex(), objInst->getObjTypeIndex()); - }, lastSel); + }; + + if(next) + selectObjOnMap(lastSel); + else + GH.windows().createAndPushWindow(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), [selectObjOnMap](int index){ selectObjOnMap(index); }, lastSel); } void AdventureMapShortcuts::nextObject() diff --git a/client/adventureMap/AdventureMapShortcuts.h b/client/adventureMap/AdventureMapShortcuts.h index 7a5bff54d..96315cda5 100644 --- a/client/adventureMap/AdventureMapShortcuts.h +++ b/client/adventureMap/AdventureMapShortcuts.h @@ -76,7 +76,7 @@ class AdventureMapShortcuts void nextTown(); void nextObject(); void zoom( int distance); - void search(); + void search(bool next); void moveHeroDirectional(const Point & direction); public: diff --git a/client/gui/Shortcut.h b/client/gui/Shortcut.h index 3bf0502d8..bd8c57a26 100644 --- a/client/gui/Shortcut.h +++ b/client/gui/Shortcut.h @@ -162,6 +162,7 @@ enum class EShortcut ADVENTURE_TO_MAIN_MENU, ADVENTURE_QUIT_GAME, ADVENTURE_SEARCH, + ADVENTURE_SEARCH_CONTINUE, // Move hero one tile in specified direction. Bound to cursors & numpad buttons ADVENTURE_MOVE_HERO_SW, diff --git a/client/gui/ShortcutHandler.cpp b/client/gui/ShortcutHandler.cpp index e64d9350d..19c3cc728 100644 --- a/client/gui/ShortcutHandler.cpp +++ b/client/gui/ShortcutHandler.cpp @@ -210,6 +210,7 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const {"adventureZoomOut", EShortcut::ADVENTURE_ZOOM_OUT }, {"adventureZoomReset", EShortcut::ADVENTURE_ZOOM_RESET }, {"adventureSearch", EShortcut::ADVENTURE_SEARCH }, + {"adventureSearchContinue", EShortcut::ADVENTURE_SEARCH_CONTINUE }, {"battleToggleHeroesStats", EShortcut::BATTLE_TOGGLE_HEROES_STATS}, {"battleToggleQueue", EShortcut::BATTLE_TOGGLE_QUEUE }, {"battleUseCreatureSpell", EShortcut::BATTLE_USE_CREATURE_SPELL }, diff --git a/config/shortcutsConfig.json b/config/shortcutsConfig.json index 111026765..e6c91b12c 100644 --- a/config/shortcutsConfig.json +++ b/config/shortcutsConfig.json @@ -57,6 +57,7 @@ "adventureZoomOut": "Keypad -", "adventureZoomReset": "Backspace", "adventureSearch": "Ctrl+F", + "adventureSearchContinue": "Alt+F", "battleAutocombat": "A", "battleAutocombatEnd": "Q", "battleCastSpell": "C", From 8e079cf0167b3f239259c939177fcfb3e19906d0 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 22:53:05 +0200 Subject: [PATCH 07/69] add search box --- client/adventureMap/AdventureMapShortcuts.cpp | 2 +- client/windows/GUIClasses.cpp | 53 ++++++++++++++----- client/windows/GUIClasses.h | 14 +++-- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index fce6ec5fe..f3ab04933 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -526,7 +526,7 @@ void AdventureMapShortcuts::search(bool next) if(next) selectObjOnMap(lastSel); else - GH.windows().createAndPushWindow(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), [selectObjOnMap](int index){ selectObjOnMap(index); }, lastSel); + GH.windows().createAndPushWindow(texts, nullptr, CGI->generaltexth->translate("vcmi.adventureMap.search.hover"), CGI->generaltexth->translate("vcmi.adventureMap.search.help"), [selectObjOnMap](int index){ selectObjOnMap(index); }, lastSel, std::vector>(), true); } void AdventureMapShortcuts::nextObject() diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 9ab54fe39..4c98c2044 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -1479,7 +1479,7 @@ void CObjectListWindow::CItem::showPopupWindow(const Point & cursorPosition) parent->onPopup(index); } -CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection, std::vector> images) +CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection, std::vector> images, bool searchBoxEnabled) : CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPGATE")), onSelect(Callback), selected(initialSelection), @@ -1489,15 +1489,14 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, std::share items.reserve(_items.size()); for(int id : _items) - { items.push_back(std::make_pair(id, LOCPLINT->cb->getObjInstance(ObjectInstanceID(id))->getObjectName())); - } + itemsVisible = items; - init(titleWidget_, _title, _descr); + init(titleWidget_, _title, _descr, searchBoxEnabled); list->scrollTo(initialSelection); } -CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection, std::vector> images) +CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection, std::vector> images, bool searchBoxEnabled) : CWindowObject(PLAYER_COLORED, ImagePath::builtin("TPGATE")), onSelect(Callback), selected(initialSelection), @@ -1508,12 +1507,13 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, st for(size_t i=0; i<_items.size(); i++) items.push_back(std::make_pair(int(i), _items[i])); + itemsVisible = items; - init(titleWidget_, _title, _descr); + init(titleWidget_, _title, _descr, searchBoxEnabled); list->scrollTo(initialSelection); } -void CObjectListWindow::init(std::shared_ptr titleWidget_, std::string _title, std::string _descr) +void CObjectListWindow::init(std::shared_ptr titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled) { titleWidget = titleWidget_; @@ -1528,24 +1528,51 @@ void CObjectListWindow::init(std::shared_ptr titleWidget_, std::stri titleWidget->pos.y =75 + pos.y - titleWidget->pos.h/2; } list = std::make_shared(std::bind(&CObjectListWindow::genItem, this, _1), - Point(14, 151), Point(0, 25), 9, items.size(), 0, 1, Rect(262, -32, 256, 256) ); + Point(14, 151), Point(0, 25), 9, itemsVisible.size(), 0, 1, Rect(262, -32, 256, 256) ); list->setRedrawParent(true); ok = std::make_shared(Point(15, 402), AnimationPath::builtin("IOKAY.DEF"), CButton::tooltip(), std::bind(&CObjectListWindow::elementSelected, this), EShortcut::GLOBAL_ACCEPT); ok->block(!list->size()); + + if(!searchBoxEnabled) + return; + + Rect r(50, 90, pos.w - 100, 16); + const ColorRGBA rectangleColor = ColorRGBA(0, 0, 0, 75); + const ColorRGBA borderColor = ColorRGBA(128, 100, 75); + const ColorRGBA grayedColor = ColorRGBA(158, 130, 105); + searchBoxRectangle = std::make_shared(r.resize(1), rectangleColor, borderColor); + searchBoxDescription = std::make_shared(r.center().x, r.center().y, FONT_SMALL, ETextAlignment::CENTER, grayedColor, CGI->generaltexth->translate("vcmi.spellBook.search")); + + searchBox = std::make_shared(r, FONT_SMALL, ETextAlignment::CENTER, true); + searchBox->setCallback([this](const std::string & text){ + searchBoxDescription->setEnabled(text.empty()); + + itemsVisible.clear(); + for(auto & item : items) + if(boost::algorithm::contains(boost::algorithm::to_lower_copy(item.second), boost::algorithm::to_lower_copy(text))) + itemsVisible.push_back(item); + + selected = 0; + list->resize(itemsVisible.size()); + list->scrollTo(0); + ok->block(!itemsVisible.size()); + + redraw(); + }); } std::shared_ptr CObjectListWindow::genItem(size_t index) { - if(index < items.size()) - return std::make_shared(this, index, items[index].second); + if(index < itemsVisible.size()) + return std::make_shared(this, index, itemsVisible[index].second); return std::shared_ptr(); } void CObjectListWindow::elementSelected() { std::function toCall = onSelect;//save - int where = items[selected].first; //required variables + int where = itemsVisible[selected].first; //required variables close();//then destroy window toCall(where);//and send selected object } @@ -1601,13 +1628,13 @@ void CObjectListWindow::keyPressed(EShortcut key) sel = 0; break; case EShortcut::MOVE_LAST: - sel = static_cast(items.size()); + sel = static_cast(itemsVisible.size()); break; default: return; } - vstd::abetween(sel, 0, items.size()-1); + vstd::abetween(sel, 0, itemsVisible.size()-1); list->scrollTo(sel); changeSelection(sel); } diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index 5e58ad6d2..6484b11ed 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -45,6 +45,7 @@ class IImage; class VideoWidget; class VideoWidgetOnce; class GraphicalPrimitiveCanvas; +class TransparentFilledRectangle; enum class EUserEvent; @@ -186,9 +187,14 @@ class CObjectListWindow : public CWindowObject std::shared_ptr ok; std::shared_ptr exit; - std::vector< std::pair > items;//all items present in list + std::shared_ptr searchBox; + std::shared_ptr searchBoxRectangle; + std::shared_ptr searchBoxDescription; - void init(std::shared_ptr titleWidget_, std::string _title, std::string _descr); + std::vector< std::pair > items; //all items present in list + std::vector< std::pair > itemsVisible; //visible items present in list + + void init(std::shared_ptr titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled); void exitPressed(); public: size_t selected;//index of currently selected item @@ -200,8 +206,8 @@ public: /// Callback will be called when OK button is pressed, returns id of selected item. initState = initially selected item /// Image can be nullptr ///item names will be taken from map objects - CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection = 0, std::vector> images = {}); - CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection = 0, std::vector> images = {}); + CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection = 0, std::vector> images = {}, bool searchBoxEnabled = false); + CObjectListWindow(const std::vector &_items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection = 0, std::vector> images = {}, bool searchBoxEnabled = false); std::shared_ptr genItem(size_t index); void elementSelected();//call callback and close this window From a4b60aca10e1f6fe0681665c03d1b16b9e24fccc Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Tue, 1 Oct 2024 23:37:27 +0200 Subject: [PATCH 08/69] cleanup --- client/adventureMap/AdventureMapShortcuts.h | 2 -- 1 file changed, 2 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.h b/client/adventureMap/AdventureMapShortcuts.h index 96315cda5..b314e7bbd 100644 --- a/client/adventureMap/AdventureMapShortcuts.h +++ b/client/adventureMap/AdventureMapShortcuts.h @@ -10,8 +10,6 @@ #pragma once -#include "../../lib/constants/EntityIdentifiers.h" - VCMI_LIB_NAMESPACE_BEGIN class Point; class Rect; From 2c16e6b4e1806688703927f784dd42aea8753c36 Mon Sep 17 00:00:00 2001 From: altiereslima Date: Tue, 1 Oct 2024 20:20:48 -0300 Subject: [PATCH 09/69] Update Portuguese Translation --- launcher/translation/portuguese.ts | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/launcher/translation/portuguese.ts b/launcher/translation/portuguese.ts index 0f4108637..1281d69a2 100644 --- a/launcher/translation/portuguese.ts +++ b/launcher/translation/portuguese.ts @@ -653,6 +653,11 @@ O download da instalação foi bem-sucedido? Neutral AI in battles IA neutra nas batalhas + + + Font Scaling (experimental) + Escala da fonte (experimental) + Enemy AI in battles @@ -963,7 +968,7 @@ Modo de tela cheia exclusivo - o jogo cobrirá toda a sua tela e usará a resolu VSync - VSync + Sincronização vertical (VSync) From e6d34156fcff89ff65ab31f34fd7a7015211874e Mon Sep 17 00:00:00 2001 From: altiereslima Date: Sun, 6 Oct 2024 13:58:54 -0300 Subject: [PATCH 10/69] Update portuguese.json --- Mods/vcmi/config/vcmi/portuguese.json | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Mods/vcmi/config/vcmi/portuguese.json b/Mods/vcmi/config/vcmi/portuguese.json index cbf548f07..7e1a5c174 100644 --- a/Mods/vcmi/config/vcmi/portuguese.json +++ b/Mods/vcmi/config/vcmi/portuguese.json @@ -12,7 +12,9 @@ "vcmi.adventureMap.monsterThreat.levels.9" : "Avassaladora", "vcmi.adventureMap.monsterThreat.levels.10" : "Mortal", "vcmi.adventureMap.monsterThreat.levels.11" : "Impossível", - "vcmi.adventureMap.monsterLevel" : "\n\nNível %LEVEL, unidade de %TOWN", + "vcmi.adventureMap.monsterLevel" : "\n\nNível %LEVEL, unidade %TOWN de ataque %ATTACK_TYPE", + "vcmi.adventureMap.monsterMeleeType" : "corpo a corpo", + "vcmi.adventureMap.monsterRangedType" : "à distância", "vcmi.adventureMap.confirmRestartGame" : "Tem certeza de que deseja reiniciar o jogo?", "vcmi.adventureMap.noTownWithMarket" : "Não há mercados disponíveis!", @@ -143,6 +145,7 @@ "vcmi.client.errors.invalidMap" : "{Mapa ou campanha inválido}\n\nFalha ao iniciar o jogo! O mapa ou campanha selecionado pode ser inválido ou corrompido. Motivo:\n%s", "vcmi.client.errors.missingCampaigns" : "{Arquivos de dados ausentes}\n\nOs arquivos de dados das campanhas não foram encontrados! Você pode estar usando arquivos de dados incompletos ou corrompidos do Heroes 3. Por favor, reinstale os dados do jogo.", "vcmi.server.errors.disconnected" : "{Erro de Rede}\n\nA conexão com o servidor do jogo foi perdida!", + "vcmi.server.errors.playerLeft" : "{Jogador Saiu}\n\nO jogador %s desconectou-se do jogo!", //%s -> player color "vcmi.server.errors.existingProcess" : "Outro processo do servidor VCMI está em execução. Por favor, termine-o antes de iniciar um novo jogo.", "vcmi.server.errors.modsToEnable" : "{Os seguintes mods são necessários}", "vcmi.server.errors.modsToDisable" : "{Os seguintes mods devem ser desativados}", From cb34b7ab507d09ed8b4d6e3eafe284e238e89c5f Mon Sep 17 00:00:00 2001 From: altiereslima Date: Thu, 10 Oct 2024 19:58:42 -0300 Subject: [PATCH 11/69] Update portuguese.json --- Mods/vcmi/config/vcmi/portuguese.json | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/Mods/vcmi/config/vcmi/portuguese.json b/Mods/vcmi/config/vcmi/portuguese.json index 7e1a5c174..d8388fe1f 100644 --- a/Mods/vcmi/config/vcmi/portuguese.json +++ b/Mods/vcmi/config/vcmi/portuguese.json @@ -61,6 +61,13 @@ "vcmi.spellBook.search" : "Procurar...", + "vcmi.spellResearch.canNotAfford" : "Você não pode se dar ao luxo de substituir {%SPELL1} por {%SPELL2}. Mas você ainda pode descartar este feitiço e continuar a pesquisa de feitiços.", + "vcmi.spellResearch.comeAgain" : "A pesquisa já foi realizada hoje. Volte amanhã.", + "vcmi.spellResearch.pay" : "Gostaria de substituir {%SPELL1} por {%SPELL2}? Ou descartar este feitiço e continuar a pesquisa de feitiços?", + "vcmi.spellResearch.research" : "Pesquisar este Feitiço", + "vcmi.spellResearch.skip" : "Pular este Feitiço", + "vcmi.spellResearch.abort" : "Abortar", + "vcmi.mainMenu.serverConnecting" : "Conectando...", "vcmi.mainMenu.serverAddressEnter" : "Insira o endereço:", "vcmi.mainMenu.serverConnectionFailed" : "Falha ao conectar", @@ -343,6 +350,12 @@ "vcmi.heroWindow.openCommander.help" : "Mostra detalhes sobre o comandante deste herói.", "vcmi.heroWindow.openBackpack.hover" : "Abrir janela da mochila de artefatos", "vcmi.heroWindow.openBackpack.help" : "Abre a janela que facilita o gerenciamento da mochila de artefatos.", + "vcmi.heroWindow.sortBackpackByCost.hover" : "Ordenar por custo", + "vcmi.heroWindow.sortBackpackByCost.help" : "Ordenar artefatos na mochila por custo.", + "vcmi.heroWindow.sortBackpackBySlot.hover" : "Ordenar por espaço", + "vcmi.heroWindow.sortBackpackBySlot.help" : "Ordenar artefatos na mochila por espaço equipado.", + "vcmi.heroWindow.sortBackpackByClass.hover" : "Ordenar por classe", + "vcmi.heroWindow.sortBackpackByClass.help" : "Ordenar artefatos na mochila por classe de artefato. Tesouro, Menor, Maior, Relíquia", "vcmi.tavernWindow.inviteHero" : "Convidar herói", From a8e84c55f673d60add8531ac8500ee9b3c7fe860 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 10 Oct 2024 20:31:11 +0000 Subject: [PATCH 12/69] Fix some of the new warnings from sonarcloud --- AI/BattleAI/AttackPossibility.cpp | 2 +- AI/Nullkiller/AIGateway.cpp | 4 +- .../Pathfinding/AIPathfinderConfig.cpp | 2 +- AI/Nullkiller/Pathfinding/Actors.cpp | 2 +- AI/Nullkiller/Pathfinding/Actors.h | 2 +- client/Client.h | 2 +- client/PlayerLocalState.cpp | 2 +- client/PlayerLocalState.h | 2 +- client/media/CVideoHandler.cpp | 2 +- client/render/AssetGenerator.cpp | 2 +- client/renderSDL/CTrueTypeFont.cpp | 16 +++---- client/widgets/TextControls.cpp | 16 +++---- client/windows/CCastleInterface.cpp | 44 +++++++++---------- client/windows/GUIClasses.cpp | 2 +- client/windows/GUIClasses.h | 2 +- client/windows/InfoWindows.cpp | 5 --- client/windows/InfoWindows.h | 1 - lib/CPlayerState.cpp | 2 +- lib/IGameCallback.h | 2 +- lib/json/JsonValidator.cpp | 2 +- lib/modding/ContentTypeHandler.cpp | 4 +- lib/texts/TextLocalizationContainer.cpp | 8 ++-- server/CGameHandler.cpp | 2 +- server/CGameHandler.h | 2 +- server/CVCMIServer.cpp | 15 +++---- server/queries/VisitQueries.cpp | 3 +- test/mock/mock_IGameCallback.h | 2 +- 27 files changed, 66 insertions(+), 84 deletions(-) diff --git a/AI/BattleAI/AttackPossibility.cpp b/AI/BattleAI/AttackPossibility.cpp index c22b7ccad..c55de09b2 100644 --- a/AI/BattleAI/AttackPossibility.cpp +++ b/AI/BattleAI/AttackPossibility.cpp @@ -58,7 +58,7 @@ void DamageCache::buildObstacleDamageCache(std::shared_ptr hb, return u->alive() && !u->isTurret() && u->getPosition().isValid(); }); - std::shared_ptr inner = std::make_shared(hb->env, hb); + auto inner = std::make_shared(hb->env, hb); for(auto stack : stacks) { diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index 99172b213..d8d5e8aed 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -649,12 +649,12 @@ void AIGateway::showBlockingDialog(const std::string & text, const std::vectordangerEvaluator->evaluateDanger(target, hero.get()); auto ratio = static_cast(danger) / hero->getTotalStrength(); - answer = 1; + answer = true; if(topObj->id != goalObjectID && nullkiller->dangerEvaluator->evaluateDanger(topObj) > 0) { // no if we do not aim to visit this object - answer = 0; + answer = false; } logAi->trace("Query hook: %s(%s) by %s danger ratio %f", target.toString(), topObj->getObjectName(), hero.name(), ratio); diff --git a/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp b/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp index 98bcddcec..7bb43fabb 100644 --- a/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp +++ b/AI/Nullkiller/Pathfinding/AIPathfinderConfig.cpp @@ -13,7 +13,7 @@ #include "Rules/AIMovementAfterDestinationRule.h" #include "Rules/AIMovementToDestinationRule.h" #include "Rules/AIPreviousNodeRule.h" -#include "../Engine//Nullkiller.h" +#include "../Engine/Nullkiller.h" #include "../../../lib/pathfinder/CPathfinder.h" diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index ae6b6446e..2c1a35ec0 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -182,7 +182,7 @@ ExchangeResult HeroActor::tryExchangeNoLock(const ChainActor * specialActor, con return &actor == specialActor; }); - result.actor = &(dynamic_cast(result.actor)->specialActors[index]); + result.actor = &(dynamic_cast(result.actor)->specialActors.at(index)); return result; } diff --git a/AI/Nullkiller/Pathfinding/Actors.h b/AI/Nullkiller/Pathfinding/Actors.h index 4451bda24..1f653fbd3 100644 --- a/AI/Nullkiller/Pathfinding/Actors.h +++ b/AI/Nullkiller/Pathfinding/Actors.h @@ -113,7 +113,7 @@ public: static const int SPECIAL_ACTORS_COUNT = 7; private: - ChainActor specialActors[SPECIAL_ACTORS_COUNT]; + std::array specialActors; std::unique_ptr exchangeMap; void setupSpecialActors(); diff --git a/client/Client.h b/client/Client.h index f8c7eaf12..ce1276b06 100644 --- a/client/Client.h +++ b/client/Client.h @@ -158,7 +158,7 @@ public: friend class CBattleCallback; //handling players actions void changeSpells(const CGHeroInstance * hero, bool give, const std::set & spells) override {}; - void setResearchedSpells(const CGTownInstance * town, int level, const std::vector spells, bool accepted) override {}; + void setResearchedSpells(const CGTownInstance * town, int level, const std::vector & spells, bool accepted) override {}; bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override {return false;}; void createBoat(const int3 & visitablePosition, BoatId type, PlayerColor initiator) override {}; void setOwner(const CGObjectInstance * obj, PlayerColor owner) override {}; diff --git a/client/PlayerLocalState.cpp b/client/PlayerLocalState.cpp index 69e8b1b5e..28d83fff4 100644 --- a/client/PlayerLocalState.cpp +++ b/client/PlayerLocalState.cpp @@ -24,7 +24,7 @@ PlayerLocalState::PlayerLocalState(CPlayerInterface & owner) { } -const PlayerSpellbookSetting & PlayerLocalState::getSpellbookSettings() +const PlayerSpellbookSetting & PlayerLocalState::getSpellbookSettings() const { return spellbookSettings; } diff --git a/client/PlayerLocalState.h b/client/PlayerLocalState.h index 0cfda1f7a..3372b6052 100644 --- a/client/PlayerLocalState.h +++ b/client/PlayerLocalState.h @@ -55,7 +55,7 @@ public: void setHeroAsleep(const CGHeroInstance * hero); void setHeroAwaken(const CGHeroInstance * hero); - const PlayerSpellbookSetting & getSpellbookSettings(); + const PlayerSpellbookSetting & getSpellbookSettings() const; void setSpellbookSettings(const PlayerSpellbookSetting & newSettings); const std::vector & getOwnedTowns(); diff --git a/client/media/CVideoHandler.cpp b/client/media/CVideoHandler.cpp index b13c2dfc0..b028e8c57 100644 --- a/client/media/CVideoHandler.cpp +++ b/client/media/CVideoHandler.cpp @@ -545,7 +545,7 @@ std::pair, si64> CAudioInstance::extractAudio(const Vide frameSamplesBuffer.resize(std::max(frameSamplesBuffer.size(), bytesToRead)); uint8_t * frameSamplesPtr = frameSamplesBuffer.data(); - int result = swr_convert(swr_ctx, &frameSamplesPtr, frame->nb_samples, (const uint8_t **)frame->data, frame->nb_samples); + int result = swr_convert(swr_ctx, &frameSamplesPtr, frame->nb_samples, const_cast(frame->data), frame->nb_samples); if (result < 0) throwFFmpegError(result); diff --git a/client/render/AssetGenerator.cpp b/client/render/AssetGenerator.cpp index 3d0d346e2..d887528e0 100644 --- a/client/render/AssetGenerator.cpp +++ b/client/render/AssetGenerator.cpp @@ -158,7 +158,7 @@ void AssetGenerator::createPlayerColoredBackground(const PlayerColor & player) assert(player.isValidPlayer()); if (!player.isValidPlayer()) { - logGlobal->error("Unable to colorize to invalid player color %d!", static_cast(player.getNum())); + logGlobal->error("Unable to colorize to invalid player color %d!", player.getNum()); return; } diff --git a/client/renderSDL/CTrueTypeFont.cpp b/client/renderSDL/CTrueTypeFont.cpp index dcf3661d6..ddff8347e 100644 --- a/client/renderSDL/CTrueTypeFont.cpp +++ b/client/renderSDL/CTrueTypeFont.cpp @@ -64,9 +64,9 @@ int CTrueTypeFont::getFontStyle(const JsonNode &config) const CTrueTypeFont::CTrueTypeFont(const JsonNode & fontConfig): data(loadData(fontConfig)), font(loadFont(fontConfig), TTF_CloseFont), - dropShadow(!fontConfig["noShadow"].Bool()), + blended(true), outline(fontConfig["outline"].Bool()), - blended(true) + dropShadow(!fontConfig["noShadow"].Bool()) { assert(font); @@ -95,14 +95,14 @@ size_t CTrueTypeFont::getLineHeightScaled() const return TTF_FontHeight(font.get()); } -size_t CTrueTypeFont::getGlyphWidthScaled(const char *data) const +size_t CTrueTypeFont::getGlyphWidthScaled(const char *text) const { - return getStringWidthScaled(std::string(data, TextOperations::getUnicodeCharacterSize(*data))); + return getStringWidthScaled(std::string(text, TextOperations::getUnicodeCharacterSize(*text))); } -bool CTrueTypeFont::canRepresentCharacter(const char * data) const +bool CTrueTypeFont::canRepresentCharacter(const char * text) const { - uint32_t codepoint = TextOperations::getUnicodeCodepoint(data, TextOperations::getUnicodeCharacterSize(*data)); + uint32_t codepoint = TextOperations::getUnicodeCodepoint(text, TextOperations::getUnicodeCharacterSize(*text)); #if SDL_TTF_VERSION_ATLEAST(2, 0, 18) return TTF_GlyphIsProvided32(font.get(), codepoint); #elif SDL_TTF_VERSION_ATLEAST(2, 0, 12) @@ -114,10 +114,10 @@ bool CTrueTypeFont::canRepresentCharacter(const char * data) const #endif } -size_t CTrueTypeFont::getStringWidthScaled(const std::string & data) const +size_t CTrueTypeFont::getStringWidthScaled(const std::string & text) const { int width; - TTF_SizeUTF8(font.get(), data.c_str(), &width, nullptr); + TTF_SizeUTF8(font.get(), text.c_str(), &width, nullptr); return width; } diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index 8975fd469..2fa440955 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -309,7 +309,7 @@ void CMultiLineLabel::splitText(const std::string & Txt, bool redrawAfter) lines.clear(); const auto & fontPtr = GH.renderHandler().loadFont(font); - int lineHeight = static_cast(fontPtr->getLineHeight()); + int lineHeight = fontPtr->getLineHeight(); lines = CMessage::breakText(Txt, pos.w, font); @@ -330,16 +330,16 @@ Rect CMultiLineLabel::getTextLocation() return pos; const auto & fontPtr = GH.renderHandler().loadFont(font); - Point textSize(pos.w, fontPtr->getLineHeight() * (int)lines.size()); - Point textOffset(pos.w - textSize.x, pos.h - textSize.y); + Point textSizeComputed(pos.w, fontPtr->getLineHeight() * lines.size()); //FIXME: how is this different from textSize member? + Point textOffset(pos.w - textSizeComputed.x, pos.h - textSizeComputed.y); switch(alignment) { - case ETextAlignment::TOPLEFT: return Rect(pos.topLeft(), textSize); - case ETextAlignment::TOPCENTER: return Rect(pos.topLeft(), textSize); - case ETextAlignment::CENTER: return Rect(pos.topLeft() + textOffset / 2, textSize); - case ETextAlignment::CENTERRIGHT: return Rect(pos.topLeft() + Point(textOffset.x, textOffset.y / 2), textSize); - case ETextAlignment::BOTTOMRIGHT: return Rect(pos.topLeft() + textOffset, textSize); + case ETextAlignment::TOPLEFT: return Rect(pos.topLeft(), textSizeComputed); + case ETextAlignment::TOPCENTER: return Rect(pos.topLeft(), textSizeComputed); + case ETextAlignment::CENTER: return Rect(pos.topLeft() + textOffset / 2, textSizeComputed); + case ETextAlignment::CENTERRIGHT: return Rect(pos.topLeft() + Point(textOffset.x, textOffset.y / 2), textSizeComputed); + case ETextAlignment::BOTTOMRIGHT: return Rect(pos.topLeft() + textOffset, textSizeComputed); } assert(0); return Rect(); diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index aea486688..28984167b 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -2007,10 +2007,10 @@ void CMageGuildScreen::updateSpells(ObjectInstanceID tID) const CGTownInstance * town = LOCPLINT->cb->getTown(townId); - for(size_t i=0; igetTown()->mageLevel; i++) + for(uint32_t i=0; igetTown()->mageLevel; i++) { - size_t spellCount = town->spellsAtLevel((int)i+1,false); //spell at level with -1 hmmm? - for(size_t j=0; jspellsAtLevel(i+1,false); //spell at level with -1 hmmm? + for(uint32_t j=0; jmageGuildLevel() && town->spells[i].size()>j) spells.push_back(std::make_shared(positions[i][j], town->spells[i][j].toSpell(), townId)); @@ -2063,30 +2063,26 @@ void CMageGuildScreen::Scroll::clickPressed(const Point & cursorPosition) resComps.push_back(std::make_shared(ComponentType::RESOURCE, i->resType, i->resVal, CComponent::ESize::medium)); } - auto showSpellResearchDialog = [this, resComps, town, cost, newSpell](){ - std::vector>> pom; - for(int i = 0; i < 3; i++) - pom.emplace_back(AnimationPath::builtin("settingsWindow/button80"), nullptr); + std::vector>> pom; + for(int i = 0; i < 3; i++) + pom.emplace_back(AnimationPath::builtin("settingsWindow/button80"), nullptr); - auto text = CGI->generaltexth->translate(LOCPLINT->cb->getResourceAmount().canAfford(cost) ? "vcmi.spellResearch.pay" : "vcmi.spellResearch.canNotAfford"); - boost::replace_first(text, "%SPELL1", spell->id.toSpell()->getNameTranslated()); - boost::replace_first(text, "%SPELL2", newSpell.toSpell()->getNameTranslated()); - auto temp = std::make_shared(text, LOCPLINT->playerID, resComps, pom); + auto text = CGI->generaltexth->translate(LOCPLINT->cb->getResourceAmount().canAfford(cost) ? "vcmi.spellResearch.pay" : "vcmi.spellResearch.canNotAfford"); + boost::replace_first(text, "%SPELL1", spell->id.toSpell()->getNameTranslated()); + boost::replace_first(text, "%SPELL2", newSpell.toSpell()->getNameTranslated()); + auto temp = std::make_shared(text, LOCPLINT->playerID, resComps, pom); - temp->buttons[0]->setOverlay(std::make_shared(ImagePath::builtin("spellResearch/accept"))); - temp->buttons[0]->addCallback([this, town](){ LOCPLINT->cb->spellResearch(town, spell->id, true); }); - temp->buttons[0]->addPopupCallback([](){ CRClickPopup::createAndPush(CGI->generaltexth->translate("vcmi.spellResearch.research")); }); - temp->buttons[0]->setEnabled(LOCPLINT->cb->getResourceAmount().canAfford(cost)); - temp->buttons[1]->setOverlay(std::make_shared(ImagePath::builtin("spellResearch/reroll"))); - temp->buttons[1]->addCallback([this, town](){ LOCPLINT->cb->spellResearch(town, spell->id, false); }); - temp->buttons[1]->addPopupCallback([](){ CRClickPopup::createAndPush(CGI->generaltexth->translate("vcmi.spellResearch.skip")); }); - temp->buttons[2]->setOverlay(std::make_shared(ImagePath::builtin("spellResearch/close"))); - temp->buttons[2]->addPopupCallback([](){ CRClickPopup::createAndPush(CGI->generaltexth->translate("vcmi.spellResearch.abort")); }); + temp->buttons[0]->setOverlay(std::make_shared(ImagePath::builtin("spellResearch/accept"))); + temp->buttons[0]->addCallback([this, town](){ LOCPLINT->cb->spellResearch(town, spell->id, true); }); + temp->buttons[0]->addPopupCallback([](){ CRClickPopup::createAndPush(CGI->generaltexth->translate("vcmi.spellResearch.research")); }); + temp->buttons[0]->setEnabled(LOCPLINT->cb->getResourceAmount().canAfford(cost)); + temp->buttons[1]->setOverlay(std::make_shared(ImagePath::builtin("spellResearch/reroll"))); + temp->buttons[1]->addCallback([this, town](){ LOCPLINT->cb->spellResearch(town, spell->id, false); }); + temp->buttons[1]->addPopupCallback([](){ CRClickPopup::createAndPush(CGI->generaltexth->translate("vcmi.spellResearch.skip")); }); + temp->buttons[2]->setOverlay(std::make_shared(ImagePath::builtin("spellResearch/close"))); + temp->buttons[2]->addPopupCallback([](){ CRClickPopup::createAndPush(CGI->generaltexth->translate("vcmi.spellResearch.abort")); }); - GH.windows().pushWindow(temp); - }; - - showSpellResearchDialog(); + GH.windows().pushWindow(temp); } else LOCPLINT->showInfoDialog(spell->getDescriptionTranslated(0), std::make_shared(ComponentType::SPELL, spell->id)); diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 46406d4d4..e8d89dfc4 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -1611,7 +1611,7 @@ void CObjectListWindow::keyPressed(EShortcut key) changeSelection(sel); } -VideoWindow::VideoWindow(VideoPath video, ImagePath rim, bool showBackground, float scaleFactor, std::function closeCb) +VideoWindow::VideoWindow(const VideoPath & video, const ImagePath & rim, bool showBackground, float scaleFactor, const std::function & closeCb) : CWindowObject(BORDERED | SHADOW_DISABLED | NEEDS_ANIMATED_BACKGROUND), closeCb(closeCb) { OBJECT_CONSTRUCTION; diff --git a/client/windows/GUIClasses.h b/client/windows/GUIClasses.h index 5e58ad6d2..883c812db 100644 --- a/client/windows/GUIClasses.h +++ b/client/windows/GUIClasses.h @@ -513,7 +513,7 @@ class VideoWindow : public CWindowObject void exit(bool skipped); public: - VideoWindow(VideoPath video, ImagePath rim, bool showBackground, float scaleFactor, std::function closeCb); + VideoWindow(const VideoPath & video, const ImagePath & rim, bool showBackground, float scaleFactor, const std::function & closeCb); void clickPressed(const Point & cursorPosition) override; void keyPressed(EShortcut key) override; diff --git a/client/windows/InfoWindows.cpp b/client/windows/InfoWindows.cpp index cabeeef13..2719c08d5 100644 --- a/client/windows/InfoWindows.cpp +++ b/client/windows/InfoWindows.cpp @@ -187,11 +187,6 @@ bool CRClickPopup::isPopupWindow() const return true; } -void CRClickPopup::close() -{ - WindowBase::close(); -} - void CRClickPopup::createAndPush(const std::string & txt, const CInfoWindow::TCompsInfo & comps) { PlayerColor player = LOCPLINT ? LOCPLINT->playerID : PlayerColor(1); //if no player, then use blue diff --git a/client/windows/InfoWindows.h b/client/windows/InfoWindows.h index a06416934..81b661339 100644 --- a/client/windows/InfoWindows.h +++ b/client/windows/InfoWindows.h @@ -64,7 +64,6 @@ public: class CRClickPopup : public WindowBase { public: - void close() override; bool isPopupWindow() const override; static std::shared_ptr createCustomInfoWindow(Point position, const CGObjectInstance * specific); diff --git a/lib/CPlayerState.cpp b/lib/CPlayerState.cpp index 2660377c6..069be91c1 100644 --- a/lib/CPlayerState.cpp +++ b/lib/CPlayerState.cpp @@ -22,9 +22,9 @@ VCMI_LIB_NAMESPACE_BEGIN PlayerState::PlayerState() : color(-1) - , playerLocalSettings(std::make_unique()) , human(false) , cheated(false) + , playerLocalSettings(std::make_unique()) , enteredWinningCheatCode(false) , enteredLosingCheatCode(false) , status(EPlayerStatus::INGAME) diff --git a/lib/IGameCallback.h b/lib/IGameCallback.h index fc1f104c3..1de95812d 100644 --- a/lib/IGameCallback.h +++ b/lib/IGameCallback.h @@ -94,7 +94,7 @@ public: virtual void showInfoDialog(InfoWindow * iw) = 0; virtual void changeSpells(const CGHeroInstance * hero, bool give, const std::set &spells)=0; - virtual void setResearchedSpells(const CGTownInstance * town, int level, const std::vector spells, bool accepted)=0; + virtual void setResearchedSpells(const CGTownInstance * town, int level, const std::vector & spells, bool accepted)=0; virtual bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) = 0; virtual void createBoat(const int3 & visitablePosition, BoatId type, PlayerColor initiator) = 0; virtual void setOwner(const CGObjectInstance * objid, PlayerColor owner)=0; diff --git a/lib/json/JsonValidator.cpp b/lib/json/JsonValidator.cpp index 0114f113d..3cb89846f 100644 --- a/lib/json/JsonValidator.cpp +++ b/lib/json/JsonValidator.cpp @@ -74,7 +74,7 @@ static int getLevenshteinDistance(const std::string & s, const std::string & t) /// Searches for keys similar to 'target' in 'candidates' map /// Returns closest match or empty string if no suitable candidates are found -static std::string findClosestMatch(JsonMap candidates, std::string target) +static std::string findClosestMatch(const JsonMap & candidates, const std::string & target) { // Maximum distance at which we can consider strings to be similar // If strings have more different symbols than this number then it is not a typo, but a completely different word diff --git a/lib/modding/ContentTypeHandler.cpp b/lib/modding/ContentTypeHandler.cpp index 0a9acb0f4..efe2feeda 100644 --- a/lib/modding/ContentTypeHandler.cpp +++ b/lib/modding/ContentTypeHandler.cpp @@ -197,8 +197,8 @@ void ContentTypeHandler::afterLoadFinalization() std::set conflictingMods; std::set resolvedConflicts; - for (auto const & conflictModData : conflictModData.Struct()) - conflictingMods.insert(conflictModData.first); + for (auto const & conflictModEntry: conflictModData.Struct()) + conflictingMods.insert(conflictModEntry.first); for (auto const & modID : conflictingMods) resolvedConflicts.merge(VLC->modh->getModDependencies(modID)); diff --git a/lib/texts/TextLocalizationContainer.cpp b/lib/texts/TextLocalizationContainer.cpp index f45898cf7..1e446defc 100644 --- a/lib/texts/TextLocalizationContainer.cpp +++ b/lib/texts/TextLocalizationContainer.cpp @@ -152,11 +152,9 @@ void TextLocalizationContainer::exportAllTexts(std::map spells, bool accepted) +void CGameHandler::setResearchedSpells(const CGTownInstance * town, int level, const std::vector & spells, bool accepted) { SetResearchedSpells cs; cs.tid = town->id; diff --git a/server/CGameHandler.h b/server/CGameHandler.h index 4448cbd22..9d896f758 100644 --- a/server/CGameHandler.h +++ b/server/CGameHandler.h @@ -107,7 +107,7 @@ public: //from IGameCallback //do sth void changeSpells(const CGHeroInstance * hero, bool give, const std::set &spells) override; - void setResearchedSpells(const CGTownInstance * town, int level, const std::vector spells, bool accepted) override; + void setResearchedSpells(const CGTownInstance * town, int level, const std::vector & spells, bool accepted) override; bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override; void setOwner(const CGObjectInstance * obj, PlayerColor owner) override; void giveExperience(const CGHeroInstance * hero, TExpType val) override; diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index c0753d2a1..7eda3a733 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -299,17 +299,12 @@ void CVCMIServer::onDisconnected(const std::shared_ptr & con std::shared_ptr c = findConnection(connection); // player may have already disconnected via clientDisconnected call - if (c) + if (c && gh && getState() == EServerState::GAMEPLAY) { - //clientDisconnected(c); - - if(gh && getState() == EServerState::GAMEPLAY) - { - LobbyClientDisconnected lcd; - lcd.c = c; - lcd.clientId = c->connectionID; - handleReceivedPack(lcd); - } + LobbyClientDisconnected lcd; + lcd.c = c; + lcd.clientId = c->connectionID; + handleReceivedPack(lcd); } } diff --git a/server/queries/VisitQueries.cpp b/server/queries/VisitQueries.cpp index 36ff95291..f5f34fbb3 100644 --- a/server/queries/VisitQueries.cpp +++ b/server/queries/VisitQueries.cpp @@ -50,7 +50,6 @@ void MapObjectVisitQuery::onRemoval(PlayerColor color) { gh->objectVisitEnded(visitingHero, players.front()); - //TODO or should it be destructor? //Can object visit affect 2 players and what would be desired behavior? if(removeObjectAfterVisit) gh->removeObject(visitedObject, color); @@ -78,7 +77,7 @@ void TownBuildingVisitQuery::onAdded(PlayerColor color) while (!visitedBuilding.empty() && owner->topQuery(color).get() == this) { visitingHero = visitedBuilding.back().hero; - auto * building = visitedTown->rewardableBuildings.at(visitedBuilding.back().building); + const auto * building = visitedTown->rewardableBuildings.at(visitedBuilding.back().building); building->onHeroVisit(visitingHero); visitedBuilding.pop_back(); } diff --git a/test/mock/mock_IGameCallback.h b/test/mock/mock_IGameCallback.h index af5dd1171..3ae574345 100644 --- a/test/mock/mock_IGameCallback.h +++ b/test/mock/mock_IGameCallback.h @@ -44,7 +44,7 @@ public: void showInfoDialog(InfoWindow * iw) override {} void changeSpells(const CGHeroInstance * hero, bool give, const std::set &spells) override {} - void setResearchedSpells(const CGTownInstance * town, int level, const std::vector spells, bool accepted) override {} + void setResearchedSpells(const CGTownInstance * town, int level, const std::vector & spells, bool accepted) override {} bool removeObject(const CGObjectInstance * obj, const PlayerColor & initiator) override {return false;} void createBoat(const int3 & visitablePosition, BoatId type, PlayerColor initiator) override {} void setOwner(const CGObjectInstance * objid, PlayerColor owner) override {} From 0c6233c77f74027876744f922ef0158333910e3a Mon Sep 17 00:00:00 2001 From: Maurycy <55395993+XCOM-HUB@users.noreply.github.com> Date: Fri, 11 Oct 2024 13:02:30 +0200 Subject: [PATCH 13/69] Update swedish.json Added new code and trimmed some texts. --- Mods/vcmi/config/vcmi/swedish.json | 239 +++++++++++++++-------------- 1 file changed, 126 insertions(+), 113 deletions(-) diff --git a/Mods/vcmi/config/vcmi/swedish.json b/Mods/vcmi/config/vcmi/swedish.json index 57f0bae33..e9145d40f 100644 --- a/Mods/vcmi/config/vcmi/swedish.json +++ b/Mods/vcmi/config/vcmi/swedish.json @@ -40,12 +40,12 @@ "vcmi.heroOverview.secondarySkills" : "Sekundärförmågor", "vcmi.heroOverview.spells" : "Trollformler", - "vcmi.radialWheel.mergeSameUnit" : "Slå samman samma varelser", + "vcmi.radialWheel.mergeSameUnit" : "Slå samman varelser av samma sort", "vcmi.radialWheel.fillSingleUnit" : "Fyll på med enstaka varelser", "vcmi.radialWheel.splitSingleUnit" : "Dela av en enda varelse", "vcmi.radialWheel.splitUnitEqually" : "Dela upp varelser lika", "vcmi.radialWheel.moveUnit" : "Flytta varelser till en annan armé", - "vcmi.radialWheel.splitUnit" : "Dela upp varelse till en annan ruta", + "vcmi.radialWheel.splitUnit" : "Dela upp varelseförband till en annan ruta", "vcmi.radialWheel.heroGetArmy" : "Hämta armé från annan hjälte", "vcmi.radialWheel.heroSwapArmy" : "Byt armé med annan hjälte", @@ -54,13 +54,20 @@ "vcmi.radialWheel.heroSwapArtifacts" : "Byt artefakter med annan hjälte", "vcmi.radialWheel.heroDismiss" : "Avfärda hjälten", - "vcmi.radialWheel.moveTop" : "Flytta till toppen", + "vcmi.radialWheel.moveTop" : "Flytta längst upp", "vcmi.radialWheel.moveUp" : "Flytta upp", "vcmi.radialWheel.moveDown" : "Flytta nedåt", - "vcmi.radialWheel.moveBottom" : "Flytta till botten", + "vcmi.radialWheel.moveBottom" : "Flytta längst ner", "vcmi.spellBook.search" : "sök...", + "vcmi.spellResearch.canNotAfford" : "Du har inte råd att byta ut '{%SPELL1}' med '{%SPELL2}'. Du kan fortfarande göra dig av med den här trollformeln och forska vidare.", + "vcmi.spellResearch.comeAgain" : "Forskningen har redan gjorts idag. Kom tillbaka imorgon.", + "vcmi.spellResearch.pay" : "Vill du byta ut '{%SPELL1}' med '{%SPELL2}'? Eller vill du göra dig av med den valda trollformeln och forska vidare?", + "vcmi.spellResearch.research" : "Forska fram denna trollformel", + "vcmi.spellResearch.skip" : "Strunta i denna trollformel", + "vcmi.spellResearch.abort" : "Avbryt", + "vcmi.mainMenu.serverConnecting" : "Ansluter...", "vcmi.mainMenu.serverAddressEnter" : "Ange adress:", "vcmi.mainMenu.serverConnectionFailed" : "Misslyckades med att ansluta", @@ -343,6 +350,12 @@ "vcmi.heroWindow.openCommander.help" : "Visar detaljer om befälhavaren för den här hjälten.", "vcmi.heroWindow.openBackpack.hover" : "Öppna artefaktryggsäcksfönster", "vcmi.heroWindow.openBackpack.help" : "Öppnar fönster som gör det enklare att hantera artefaktryggsäcken.", + "vcmi.heroWindow.sortBackpackByCost.hover" : "Sortera efter kostnad", + "vcmi.heroWindow.sortBackpackByCost.help" : "Sorterar artefakter i ryggsäcken efter kostnad.", + "vcmi.heroWindow.sortBackpackBySlot.hover" : "Sortera efter plats", + "vcmi.heroWindow.sortBackpackBySlot.help" : "Sorterar artefakter i ryggsäcken efter utrustad plats.", + "vcmi.heroWindow.sortBackpackByClass.hover" : "Sortera efter klass", + "vcmi.heroWindow.sortBackpackByClass.help" : "Sorterar artefakter i ryggsäcken efter artefaktklass (skatt, mindre, större, relik)", "vcmi.tavernWindow.inviteHero" : "Bjud in hjälte", @@ -355,8 +368,8 @@ "vcmi.creatureWindow.returnArtifact.hover" : "Återlämna artefakt", "vcmi.creatureWindow.returnArtifact.help" : "Klicka på den här knappen för att lägga tillbaka artefakten i hjältens ryggsäck.", - "vcmi.questLog.hideComplete.hover" : "Gömmer alla slutförda uppdrag", - "vcmi.questLog.hideComplete.help" : "Dölj alla slutförda uppdrag.", + "vcmi.questLog.hideComplete.hover" : "Dölj alla slutförda uppdrag", + "vcmi.questLog.hideComplete.help" : "Gömmer undan alla slutförda uppdrag.", "vcmi.randomMapTab.widgets.randomTemplate" : "(Slumpmässig)", "vcmi.randomMapTab.widgets.templateLabel" : "Mall", @@ -365,22 +378,22 @@ "vcmi.randomMapTab.widgets.roadTypesLabel" : "Vägtyper", "vcmi.optionsTab.turnOptions.hover" : "Turomgångsalternativ", - "vcmi.optionsTab.turnOptions.help" : "Välj alternativ för turomgångs-timer och simultana turer", + "vcmi.optionsTab.turnOptions.help" : "Ställ in turomgångs-timern och samtidiga turomgångar", "vcmi.optionsTab.chessFieldBase.hover" : "Bas-timern", "vcmi.optionsTab.chessFieldTurn.hover" : "Tur-timern", "vcmi.optionsTab.chessFieldBattle.hover" : "Strids-timern", "vcmi.optionsTab.chessFieldUnit.hover" : "Enhets-timern", - "vcmi.optionsTab.chessFieldBase.help" : "Används när {Tur-timern} når '0'. Ställs in en gång i början av spelet. När den når '0' avslutas den aktuella turomgången (pågående strid avslutas med förlust).", - "vcmi.optionsTab.chessFieldTurnAccumulate.help" : "Används utanför strid eller när {Strids-timern} tar slut. Återställs varje turomgång. Outnyttjad tid läggs till i {Bas-timern} till nästa turomgång.", + "vcmi.optionsTab.chessFieldBase.help" : "Används när {Tur-timern} når 0. Ställs in i början av spelet. Vid 0 avslutas turomgången (pågående strid avslutas med förlust).", + "vcmi.optionsTab.chessFieldTurnAccumulate.help" : "Används utanför strid eller när {Strids-timern} tar slut. Återställs varje turomgång. Outnyttjad tid läggs till i {Bas-timern}.", "vcmi.optionsTab.chessFieldTurnDiscard.help" : "Används utanför strid eller när {Strids-timern} tar slut. Återställs varje turomgång. Outnyttjad tid går förlorad.", "vcmi.optionsTab.chessFieldBattle.help" : "Används i strider med AI eller i PvP-strid när {Enhets-timern} tar slut. Återställs i början av varje strid.", - "vcmi.optionsTab.chessFieldUnitAccumulate.help" : "Används när du styr din enhet i PvP-strid. Outnyttjad tid läggs till i {Strids-timern} när enheten har avslutat sin turomgång.", - "vcmi.optionsTab.chessFieldUnitDiscard.help" : "Används när du styr din enhet i PvP-strid. Återställs i början av varje enhets turomgång. Outnyttjad tid går förlorad.", + "vcmi.optionsTab.chessFieldUnitAccumulate.help" : "Används när du styr dina enheter i PvP-strid. Outnyttjad tid läggs till i {Strids-timern} när enheten har avslutat sin turomgång.", + "vcmi.optionsTab.chessFieldUnitDiscard.help" : "Används när du styr dina enheter i PvP-strid. Återställs i början av varje enhets turomgång. Outnyttjad tid går förlorad.", "vcmi.optionsTab.accumulate" : "Ackumulera", - "vcmi.optionsTab.simturnsTitle" : "Simultana turomgångar", + "vcmi.optionsTab.simturnsTitle" : "Samtidiga turomgångar", "vcmi.optionsTab.simturnsMin.hover" : "Åtminstone i", "vcmi.optionsTab.simturnsMax.hover" : "Som mest i", "vcmi.optionsTab.simturnsAI.hover" : "(Experimentell) Simultana AI-turomgångar", @@ -388,7 +401,7 @@ "vcmi.optionsTab.simturnsMax.help" : "Spela samtidigt som andra spelare under ett angivet antal dagar eller tills en tillräckligt nära kontakt inträffar med en annan spelare", "vcmi.optionsTab.simturnsAI.help" : "{Simultana AI-turomgångar}\nExperimentellt alternativ. Tillåter AI-spelare att agera samtidigt som den mänskliga spelaren när simultana turomgångar är aktiverade.", - "vcmi.optionsTab.turnTime.select" : "Timer-inställningar för turomgångar", + "vcmi.optionsTab.turnTime.select" : "Ställ in turomgångs-timer", "vcmi.optionsTab.turnTime.unlimited" : "Obegränsat med tid", "vcmi.optionsTab.turnTime.classic.1" : "Klassisk timer: 1 minut", "vcmi.optionsTab.turnTime.classic.2" : "Klassisk timer: 2 minuter", @@ -403,15 +416,15 @@ "vcmi.optionsTab.turnTime.chess.2" : "Schack: 02:00 + 01:00 + 00:15 + 00:00", "vcmi.optionsTab.turnTime.chess.1" : "Schack: 01:00 + 01:00 + 00:00 + 00:00", - "vcmi.optionsTab.simturns.select" : "Simultana/samtidiga turomgångsinställningar", - "vcmi.optionsTab.simturns.none" : "Inga simultana/samtidiga turer", - "vcmi.optionsTab.simturns.tillContactMax" : "Sam-tur: Fram till kontakt", - "vcmi.optionsTab.simturns.tillContact1" : "Sam-tur: 1 vecka, bryt vid kontakt", - "vcmi.optionsTab.simturns.tillContact2" : "Sam-tur: 2 veckor, bryt vid kontakt", - "vcmi.optionsTab.simturns.tillContact4" : "Sam-tur: 1 månad, bryt vid kontakt", - "vcmi.optionsTab.simturns.blocked1" : "Sam-tur: 1 vecka, kontakter blockerade", - "vcmi.optionsTab.simturns.blocked2" : "Sam-tur: 2 veckor, kontakter blockerade", - "vcmi.optionsTab.simturns.blocked4" : "Sam-tur: 1 månad, kontakter blockerade", + "vcmi.optionsTab.simturns.select" : "Ställ in samtidiga turomgångar", + "vcmi.optionsTab.simturns.none" : "Inga samtidiga turomgångar", + "vcmi.optionsTab.simturns.tillContactMax" : "Samtur: Fram till närkontakt", + "vcmi.optionsTab.simturns.tillContact1" : "Samtur: 1 vecka (bryts vid närkontakt)", + "vcmi.optionsTab.simturns.tillContact2" : "Samtur: 2 veckor (bryts vid närkontakt)", + "vcmi.optionsTab.simturns.tillContact4" : "Samtur: 1 månad (bryts vid närkontakt)", + "vcmi.optionsTab.simturns.blocked1" : "Samtur: 1 vecka (närkontakt blockerad)", + "vcmi.optionsTab.simturns.blocked2" : "Samtur: 2 veckor (närkontakt blockerad)", + "vcmi.optionsTab.simturns.blocked4" : "Samtur: 1 månad (närkontakt blockerad)", // Translation note: translate strings below using form that is correct for "0 days", "1 day" and "2 days" in your language // Using this information, VCMI will automatically select correct plural form for every possible amount @@ -521,155 +534,155 @@ "core.seerhut.quest.reachDate.visit.5" : "Stängt fram till %s.", "core.bonus.ADDITIONAL_ATTACK.name" : "Dubbelslag", - "core.bonus.ADDITIONAL_ATTACK.description" : "Attackerar två gånger", + "core.bonus.ADDITIONAL_ATTACK.description" : "Attackerar två gånger.", "core.bonus.ADDITIONAL_RETALIATION.name" : "Ytterligare motattacker", - "core.bonus.ADDITIONAL_RETALIATION.description" : "Kan slå tillbaka ${val} extra gånger", + "core.bonus.ADDITIONAL_RETALIATION.description" : "Kan slå tillbaka ${val} extra gånger.", "core.bonus.AIR_IMMUNITY.name" : "Luft-immunitet", - "core.bonus.AIR_IMMUNITY.description" : "Immun mot alla trollformler från skolan för luftmagi", + "core.bonus.AIR_IMMUNITY.description" : "Immun mot alla luftmagi-trollformler.", "core.bonus.ATTACKS_ALL_ADJACENT.name" : "Attackera runtomkring", - "core.bonus.ATTACKS_ALL_ADJACENT.description" : "Attackerar alla angränsande fiender", - "core.bonus.BLOCKS_RETALIATION.name" : "Blockera närstrids-motattack", - "core.bonus.BLOCKS_RETALIATION.description" : "Fienden kan inte slå tillbaka/retaliera", - "core.bonus.BLOCKS_RANGED_RETALIATION.name" : "Blockera fjärrstrids-motattack", - "core.bonus.BLOCKS_RANGED_RETALIATION.description" : "Fienden kan inte retaliera på avstånd genom att använda en distansattack", - "core.bonus.CATAPULT.name" : "Katapult", - "core.bonus.CATAPULT.description" : "Attackerar belägringsmurar", - "core.bonus.CHANGES_SPELL_COST_FOR_ALLY.name" : "Minska trollformelkostnaden (${val})", - "core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description" : "Minskar trollformelkostnaden för hjälten med ${val}", + "core.bonus.ATTACKS_ALL_ADJACENT.description" : "Attackerar alla angränsande fiender.", + "core.bonus.BLOCKS_RETALIATION.name" : "Retaliera ej i närstrid", + "core.bonus.BLOCKS_RETALIATION.description" : "Fienden kan inte slå tillbaka/retaliera.", + "core.bonus.BLOCKS_RANGED_RETALIATION.name" : "Retaliera ej på avstånd", + "core.bonus.BLOCKS_RANGED_RETALIATION.description" : "Fienden kan inte retaliera på avstånd.", + "core.bonus.CATAPULT.name" : "Katapult-attack", + "core.bonus.CATAPULT.description" : "Attackerar belägringsmurar.", + "core.bonus.CHANGES_SPELL_COST_FOR_ALLY.name" : "Minska magikostnad (${val})", + "core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description" : "Minskar magikostnaden för hjälten med ${val}.", "core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.name" : "Magisk dämpare (${val})", - "core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description": "Ökar trollformelkostnaden för fiendens trollformler med ${val}", + "core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description": "Ökar fiendens magikostnad med ${val}.", "core.bonus.CHARGE_IMMUNITY.name" : "Galoppanfalls-immunitet", - "core.bonus.CHARGE_IMMUNITY.description" : "Immun mot ryttares och tornerares galopperande ridanfall", + "core.bonus.CHARGE_IMMUNITY.description" : "Immun mot ryttares galopperande ridanfall.", "core.bonus.DARKNESS.name" : "I skydd av mörkret", - "core.bonus.DARKNESS.description" : "Skapar ett mörkerhölje med en rut-radie på ${val} som gäckar dina fiender", + "core.bonus.DARKNESS.description" : "Skapar ett mörkerhölje med rutradien ${val}.", "core.bonus.DEATH_STARE.name" : "Dödsblick (${val}%)", - "core.bonus.DEATH_STARE.description" : "Varje 'Dödsblick' har ${val}% chans att döda den översta fiendeenheten", + "core.bonus.DEATH_STARE.description" : "Varje dödsblick har ${val}% chans att döda.", "core.bonus.DEFENSIVE_STANCE.name" : "Försvarshållning", - "core.bonus.DEFENSIVE_STANCE.description" : "När du väljer att försvara en enhet så får den +${val} extra försvar", + "core.bonus.DEFENSIVE_STANCE.description" : "+${val} extra försvar när du försvarar dig.", "core.bonus.DESTRUCTION.name" : "Förintelse", - "core.bonus.DESTRUCTION.description" : "Har ${val}% chans att döda extra enheter efter attack", + "core.bonus.DESTRUCTION.description" : "${val}% chans att ta död på fler efter attack.", "core.bonus.DOUBLE_DAMAGE_CHANCE.name" : "Dödsstöt", - "core.bonus.DOUBLE_DAMAGE_CHANCE.description" : "Har ${val}% chans att utdela dubbel basskada vid attack", + "core.bonus.DOUBLE_DAMAGE_CHANCE.description" : "${val}% chans till dubbel basskada vid attack.", "core.bonus.DRAGON_NATURE.name" : "Drake", - "core.bonus.DRAGON_NATURE.description" : "Varelsen har en draknatur", + "core.bonus.DRAGON_NATURE.description" : "Varelsen har en draknatur.", "core.bonus.EARTH_IMMUNITY.name" : "Jord-immunitet", - "core.bonus.EARTH_IMMUNITY.description" : "Immun mot alla trollformler från skolan för jordmagi", + "core.bonus.EARTH_IMMUNITY.description" : "Immun mot alla jordmagi-trollformler.", "core.bonus.ENCHANTER.name" : "Förtrollare", - "core.bonus.ENCHANTER.description" : "Kan kasta ${subtyp.spell} på alla varje turomgång", + "core.bonus.ENCHANTER.description" : "Kastar mass-${subtype.spell} varje turomgång.", "core.bonus.ENCHANTED.name" : "Förtrollad", - "core.bonus.ENCHANTED.description" : "Påverkas av permanent ${subtype.spell}", + "core.bonus.ENCHANTED.description" : "Påverkas av permanent ${subtype.spell}.", "core.bonus.ENEMY_ATTACK_REDUCTION.name" : "Avfärda attack (${val}%)", - "core.bonus.ENEMY_ATTACK_REDUCTION.description" : "När du blir attackerad ignoreras ${val}% av angriparens attack", + "core.bonus.ENEMY_ATTACK_REDUCTION.description" : "Ignorerar ${val}% av angriparens attack.", "core.bonus.ENEMY_DEFENCE_REDUCTION.name" : "Förbigå försvar (${val}%)", - "core.bonus.ENEMY_DEFENCE_REDUCTION.description" : "När du attackerar ignoreras ${val}% av försvararens försvar", + "core.bonus.ENEMY_DEFENCE_REDUCTION.description" : "Din attack ignorerar ${val}% av fiendens försvar.", "core.bonus.FIRE_IMMUNITY.name" : "Eld-immunitet", - "core.bonus.FIRE_IMMUNITY.description" : "Immun mot alla trollformler från skolan för eldmagi", + "core.bonus.FIRE_IMMUNITY.description" : "Immun mot alla eldmagi-trollformler.", "core.bonus.FIRE_SHIELD.name" : "Eldsköld (${val}%)", - "core.bonus.FIRE_SHIELD.description" : "Reflekterar en del av närstridsskadorna", + "core.bonus.FIRE_SHIELD.description" : "Reflekterar en del av närstridsskadorna.", "core.bonus.FIRST_STRIKE.name" : "Första slaget", - "core.bonus.FIRST_STRIKE.description" : "Denna varelse gör en motattack innan den blir attackerad", + "core.bonus.FIRST_STRIKE.description" : "Retalierar innan den blir attackerad.", "core.bonus.FEAR.name" : "Rädsla", - "core.bonus.FEAR.description" : "Orsakar rädsla på ett fiendeförband", + "core.bonus.FEAR.description" : "Orsakar rädsla på ett fiendeförband.", "core.bonus.FEARLESS.name" : "Orädd", - "core.bonus.FEARLESS.description" : "Immun mot rädsla", + "core.bonus.FEARLESS.description" : "Immun mot rädsla.", "core.bonus.FEROCITY.name" : "Vildsint", - "core.bonus.FEROCITY.description" : "Attackerar ${val} extra gång(er) om någon dödas", + "core.bonus.FEROCITY.description" : "+${val} extra attack(er) om någon dödas.", "core.bonus.FLYING.name" : "Flygande", - "core.bonus.FLYING.description" : "Flyger vid förflyttning (ignorerar hinder)", + "core.bonus.FLYING.description" : "Flyger vid förflyttning (ignorerar hinder).", "core.bonus.FREE_SHOOTING.name" : "Skjut på nära håll", - "core.bonus.FREE_SHOOTING.description" : "Kan använda distansattacker på närstridsavstånd", + "core.bonus.FREE_SHOOTING.description" : "Använd distansattacker på närstridsavstånd.", "core.bonus.GARGOYLE.name" : "Stenfigur", - "core.bonus.GARGOYLE.description" : "Kan varken upplivas eller läkas", + "core.bonus.GARGOYLE.description" : "Kan varken upplivas eller läkas.", "core.bonus.GENERAL_DAMAGE_REDUCTION.name" : "Minska skada (${val}%)", - "core.bonus.GENERAL_DAMAGE_REDUCTION.description" : "Reducerar skadan från distans- och närstrids-attacker", - "core.bonus.HATE.name" : "Hatar ${subtyp.varelse}", - "core.bonus.HATE.description" : "Gör ${val}% mer skada mot ${subtyp.varelse}", + "core.bonus.GENERAL_DAMAGE_REDUCTION.description" : "Reducerar skadan från inkommande attacker.", + "core.bonus.HATE.name" : "Hatar: ${subtype.creature}", + "core.bonus.HATE.description" : "Gör ${val}% mer skada mot ${subtype.creature}.", "core.bonus.HEALER.name" : "Helare", - "core.bonus.HEALER.description" : "Helar/läker allierade enheter", + "core.bonus.HEALER.description" : "Helar/läker allierade enheter.", "core.bonus.HP_REGENERATION.name" : "Självläkande", - "core.bonus.HP_REGENERATION.description" : "Får tillbaka ${val} hälsa (träffpoäng) varje runda", + "core.bonus.HP_REGENERATION.description" : "Återfår ${val} hälsa (träffpoäng) varje runda.", "core.bonus.JOUSTING.name" : "Galopperande ridanfall", - "core.bonus.JOUSTING.description" : "Orsakar +${val}% mer skada för varje ruta som förflyttas innan attack", + "core.bonus.JOUSTING.description" : "+${val}% skada per rutförflyttning före attack.", "core.bonus.KING.name" : "Kung", - "core.bonus.KING.description" : "Sårbar för 'Dräpar'-nivå ${val} eller högre", - "core.bonus.LEVEL_SPELL_IMMUNITY.name" : "Förtrollningsimmunitet 1-${val}", - "core.bonus.LEVEL_SPELL_IMMUNITY.description" : "Immun mot trollformler på nivå 1-${val}", - "core.bonus.LIMITED_SHOOTING_RANGE.name" : "Begränsad räckvidd för skjutning", - "core.bonus.LIMITED_SHOOTING_RANGE.description" : "Kan inte sikta på enheter längre bort än ${val} rutor", - "core.bonus.LIFE_DRAIN.name" : "Dränerar livskraft (${val}%)", - "core.bonus.LIFE_DRAIN.description" : "Dränerar ${val}% hälsa (träffpoäng) av utdelad skada", - "core.bonus.MANA_CHANNELING.name" : "Kanalisera trollformelspoäng ${val}%", - "core.bonus.MANA_CHANNELING.description" : "Ger din hjälte ${val}% av fiendens spenderade trollformelspoäng i strid", - "core.bonus.MANA_DRAIN.name" : "Dränera trollformelspoäng", - "core.bonus.MANA_DRAIN.description" : "Dränerar ${val} trollformelspoäng varje tur", + "core.bonus.KING.description" : "Sårbar för Dräpar-nivå ${val} eller högre.", + "core.bonus.LEVEL_SPELL_IMMUNITY.name" : "Trolldomsimmunitet 1-${val}", + "core.bonus.LEVEL_SPELL_IMMUNITY.description" : "Immun mot nivå 1-${val}-trollformler.", + "core.bonus.LIMITED_SHOOTING_RANGE.name" : "Begränsad skjuträckvidd", + "core.bonus.LIMITED_SHOOTING_RANGE.description" : "Skjuträckvidd: ${val} rutor.", + "core.bonus.LIFE_DRAIN.name" : "Dränera livskraft (${val}%)", + "core.bonus.LIFE_DRAIN.description" : "Dränera ${val}% hälsa av den vållade skadan.", + "core.bonus.MANA_CHANNELING.name" : "Kanalisera magi (${val}%)", + "core.bonus.MANA_CHANNELING.description" : "Ger din hjälte ${val}% av fiendens spenderade mana.", + "core.bonus.MANA_DRAIN.name" : "Dränera mana", + "core.bonus.MANA_DRAIN.description" : "Dränerar ${val} mana från fienden varje tur.", "core.bonus.MAGIC_MIRROR.name" : "Magisk spegel (${val}%)", - "core.bonus.MAGIC_MIRROR.description" : "${val}% chans att reflektera en offensiv trollformel på en fiendeenhet", + "core.bonus.MAGIC_MIRROR.description" : "${val}% chans att reflektera skadliga trollformler.", "core.bonus.MAGIC_RESISTANCE.name" : "Magiskt motstånd (${val}%)", - "core.bonus.MAGIC_RESISTANCE.description" : "Har en ${val}% chans att motstå en skadlig trollformel", - "core.bonus.MIND_IMMUNITY.name" : "Immunitet mot sinnesförtrollningar", - "core.bonus.MIND_IMMUNITY.description" : "Immun mot förtrollningar som påverkar dina sinnen", - "core.bonus.NO_DISTANCE_PENALTY.name" : "Ingen avståndsbestraffning", - "core.bonus.NO_DISTANCE_PENALTY.description" : "Gör full skada på vilket avstånd som helst i strid", - "core.bonus.NO_MELEE_PENALTY.name" : "Ingen närstridsbestraffning", - "core.bonus.NO_MELEE_PENALTY.description" : "Varelsen har ingen närstridsbestraffning", + "core.bonus.MAGIC_RESISTANCE.description" : "${val}% chans att motstå en skadlig trollformel.", + "core.bonus.MIND_IMMUNITY.name" : "Immun mot sinnesmagi", + "core.bonus.MIND_IMMUNITY.description" : "Immun mot magi som påverkar dina sinnen.", + "core.bonus.NO_DISTANCE_PENALTY.name" : "Långdistansskytt", + "core.bonus.NO_DISTANCE_PENALTY.description" : "Gör full skada på alla avstånd i strid.", + "core.bonus.NO_MELEE_PENALTY.name" : "Närstridsspecialist", + "core.bonus.NO_MELEE_PENALTY.description" : "Ingen närstridsbestraffning.", "core.bonus.NO_MORALE.name" : "Ingen Moralpåverkan", - "core.bonus.NO_MORALE.description" : "Är immun mot moraliska effekter och har alltid neutral moral", + "core.bonus.NO_MORALE.description" : "Immun mot moral-effekter (neutral moral).", "core.bonus.NO_WALL_PENALTY.name" : "Ingen murbestraffning", - "core.bonus.NO_WALL_PENALTY.description" : "Orsakar full skada mot fiender bakom en mur", + "core.bonus.NO_WALL_PENALTY.description" : "Gör full skada mot fiender bakom en mur.", "core.bonus.NON_LIVING.name" : "Icke levande", - "core.bonus.NON_LIVING.description" : "Påverkas inte av vissa effekter som levande/odöda gör", + "core.bonus.NON_LIVING.description" : "Immunitet mot många effekter.", "core.bonus.RANDOM_SPELLCASTER.name" : "Slumpmässig besvärjare", - "core.bonus.RANDOM_SPELLCASTER.description" : "Kan kasta trollformler som väljs slumpmässigt", + "core.bonus.RANDOM_SPELLCASTER.description" : "Kastar trollformler som väljs slumpmässigt.", "core.bonus.RANGED_RETALIATION.name" : "Motattacker på avstånd", - "core.bonus.RANGED_RETALIATION.description" : "Kan retaliera/motattackera på avstånd", - "core.bonus.RECEPTIVE.name" : "Mottaglig", - "core.bonus.RECEPTIVE.description" : "Ingen immunitet mot vänliga besvärjelser", + "core.bonus.RANGED_RETALIATION.description" : "Kan retaliera/motattackera på avstånd.", + "core.bonus.RECEPTIVE.name" : "Magiskt mottaglig", + "core.bonus.RECEPTIVE.description" : "Ingen immunitet mot vänliga trollformler.", "core.bonus.REBIRTH.name" : "Återfödelse (${val}%)", - "core.bonus.REBIRTH.description" : "${val}% av enheterna kommer att återuppväckas efter döden", + "core.bonus.REBIRTH.description" : "${val}% återuppväcks efter döden.", "core.bonus.RETURN_AFTER_STRIKE.name" : "Återvänder efter närstrid", - "core.bonus.RETURN_AFTER_STRIKE.description" : "Efter närstridsattack återvänder den till sin ursprungliga ruta", + "core.bonus.RETURN_AFTER_STRIKE.description" : "Återvänder till sin ruta efter attack.", "core.bonus.REVENGE.name" : "Hämnd", - "core.bonus.REVENGE.description" : "Orsakar mer skada om den själv blivit skadad", + "core.bonus.REVENGE.description" : "Extra skada om den själv blivit skadad.", "core.bonus.SHOOTER.name" : "Distans-attack", - "core.bonus.SHOOTER.description" : "Varelsen kan skjuta/attackera på avstånd", + "core.bonus.SHOOTER.description" : "Varelsen kan skjuta/attackera på avstånd.", "core.bonus.SHOOTS_ALL_ADJACENT.name" : "Skjuter alla i närheten", - "core.bonus.SHOOTS_ALL_ADJACENT.description" : "Dess distans-attacker drabbar alla mål i ett litet område", + "core.bonus.SHOOTS_ALL_ADJACENT.description" : "Distans-attack drabbar alla inom räckhåll.", "core.bonus.SOUL_STEAL.name" : "Själtjuv", - "core.bonus.SOUL_STEAL.description" : "Återuppväcker ${val} av sina egna för varje dödad fiendeenhet", + "core.bonus.SOUL_STEAL.description" : "Återuppväcker ${val} av sina egna/dödad fiende.", "core.bonus.SPELLCASTER.name" : "Besvärjare", - "core.bonus.SPELLCASTER.description" : "Kan kasta ${subtype.spell}", + "core.bonus.SPELLCASTER.description" : "Kan kasta: ${subtype.spell}.", "core.bonus.SPELL_AFTER_ATTACK.name" : "Besvärja efter attack", - "core.bonus.SPELL_AFTER_ATTACK.description" : "Har ${val}% chans att kasta ${subtype.spell} efter anfall", + "core.bonus.SPELL_AFTER_ATTACK.description" : "${val}% chans för '${subtype.spell}' efter attack.", "core.bonus.SPELL_BEFORE_ATTACK.name" : "Besvärja före attack", - "core.bonus.SPELL_BEFORE_ATTACK.description" : "Har ${val}% chans att kasta ${subtype.spell} före anfall", + "core.bonus.SPELL_BEFORE_ATTACK.description" : "${val}% chans för '${subtype.spell}' före attack.", "core.bonus.SPELL_DAMAGE_REDUCTION.name" : "Trolldoms-resistens", - "core.bonus.SPELL_DAMAGE_REDUCTION.description" : "Skadan från trollformler är reducet med ${val}%.", + "core.bonus.SPELL_DAMAGE_REDUCTION.description" : "Reducerar magisk-skada med ${val}%.", "core.bonus.SPELL_IMMUNITY.name" : "Trolldoms-immunitet", - "core.bonus.SPELL_IMMUNITY.description" : "Immun mot ${subtype.spell}", - "core.bonus.SPELL_LIKE_ATTACK.name" : "Trolldomsliknande attack", - "core.bonus.SPELL_LIKE_ATTACK.description" : "Attackerar med ${subtype.spell}", + "core.bonus.SPELL_IMMUNITY.description" : "Immun mot '${subtype.spell}'.", + "core.bonus.SPELL_LIKE_ATTACK.name" : "Magisk attack", + "core.bonus.SPELL_LIKE_ATTACK.description" : "Attackerar med '${subtype.spell}'.", "core.bonus.SPELL_RESISTANCE_AURA.name" : "Motståndsaura", - "core.bonus.SPELL_RESISTANCE_AURA.description" : "Närbelägna förband får ${val}% magi-resistens", + "core.bonus.SPELL_RESISTANCE_AURA.description" : "Närbelägna förband får ${val}% magi-resistens.", "core.bonus.SUMMON_GUARDIANS.name" : "Åkalla väktare", - "core.bonus.SUMMON_GUARDIANS.description" : "I början av striden åkallas ${subtype.creature} (${val}%)", + "core.bonus.SUMMON_GUARDIANS.description" : "Vid strid åkallas: ${subtype.creature} ${val}%.", "core.bonus.SYNERGY_TARGET.name" : "Synergibar", - "core.bonus.SYNERGY_TARGET.description" : "Denna varelse är sårbar för synergieffekt", + "core.bonus.SYNERGY_TARGET.description" : "Denna varelse är sårbar för synergieffekt.", "core.bonus.TWO_HEX_ATTACK_BREATH.name" : "Dödlig andedräkt", - "core.bonus.TWO_HEX_ATTACK_BREATH.description" : "Andningsattack (2 rutors räckvidd)", + "core.bonus.TWO_HEX_ATTACK_BREATH.description" : "Andningsattack (2 rutors räckvidd).", "core.bonus.THREE_HEADED_ATTACK.name" : "Trehövdad attack", - "core.bonus.THREE_HEADED_ATTACK.description" : "Attackerar tre angränsande enheter", + "core.bonus.THREE_HEADED_ATTACK.description" : "Attackerar tre angränsande enheter.", "core.bonus.TRANSMUTATION.name" : "Transmutation", - "core.bonus.TRANSMUTATION.description" : "${val}% chans att förvandla angripen enhet till en annan typ", + "core.bonus.TRANSMUTATION.description" : "${val}% chans att förvandla angripen enhet.", "core.bonus.UNDEAD.name" : "Odöd", - "core.bonus.UNDEAD.description" : "Varelsen är odöd", + "core.bonus.UNDEAD.description" : "Varelsen är odöd.", "core.bonus.UNLIMITED_RETALIATIONS.name" : "Slår tillbaka varje gång", - "core.bonus.UNLIMITED_RETALIATIONS.description" : "Obegränsat antal motattacker", + "core.bonus.UNLIMITED_RETALIATIONS.description" : "Obegränsat antal motattacker.", "core.bonus.WATER_IMMUNITY.name" : "Vatten-immunitet", - "core.bonus.WATER_IMMUNITY.description" : "Immun mot alla trollformler från vattenmagiskolan", + "core.bonus.WATER_IMMUNITY.description" : "Immun mot alla vattenmagi-trollformler.", "core.bonus.WIDE_BREATH.name" : "Bred dödlig andedräkt", - "core.bonus.WIDE_BREATH.description" : "Bred andningsattack (flera rutor)", + "core.bonus.WIDE_BREATH.description" : "Bred andningsattack (flera rutor).", "core.bonus.DISINTEGRATE.name" : "Desintegrerar", - "core.bonus.DISINTEGRATE.description" : "Ingen kropp lämnas kvar efter dödsögonblicket", + "core.bonus.DISINTEGRATE.description" : "Ingen kropp lämnas kvar på slagfältet.", "core.bonus.INVINCIBLE.name" : "Oövervinnerlig", - "core.bonus.INVINCIBLE.description" : "Kan inte påverkas av någonting" + "core.bonus.INVINCIBLE.description" : "Kan inte påverkas av någonting." } From b67b43c811c8eebc6292fc48f3e9092b610e73c4 Mon Sep 17 00:00:00 2001 From: kdmcser Date: Sat, 12 Oct 2024 12:50:02 +0800 Subject: [PATCH 14/69] do lupdate and update Chinese translation --- Mods/vcmi/config/vcmi/chinese.json | 2 +- launcher/translation/chinese.ts | 185 ++++++++++++++--------- launcher/translation/czech.ts | 185 ++++++++++++++--------- launcher/translation/english.ts | 219 ++++++++++++++++----------- launcher/translation/french.ts | 185 ++++++++++++++--------- launcher/translation/german.ts | 185 ++++++++++++++--------- launcher/translation/polish.ts | 185 ++++++++++++++--------- launcher/translation/portuguese.ts | 189 ++++++++++++++--------- launcher/translation/russian.ts | 235 +++++++++++++++++------------ launcher/translation/spanish.ts | 185 ++++++++++++++--------- launcher/translation/swedish.ts | 193 ++++++++++++++--------- launcher/translation/ukrainian.ts | 185 ++++++++++++++--------- launcher/translation/vietnamese.ts | 185 ++++++++++++++--------- 13 files changed, 1417 insertions(+), 901 deletions(-) diff --git a/Mods/vcmi/config/vcmi/chinese.json b/Mods/vcmi/config/vcmi/chinese.json index a36a923ce..44960a60a 100644 --- a/Mods/vcmi/config/vcmi/chinese.json +++ b/Mods/vcmi/config/vcmi/chinese.json @@ -581,7 +581,7 @@ "core.bonus.GARGOYLE.description": "不能被复活或治疗", "core.bonus.GENERAL_DAMAGE_REDUCTION.name": "减少伤害 (${val}%)", "core.bonus.GENERAL_DAMAGE_REDUCTION.description": "减少从远程和近战中遭受的物理伤害", - "core.bonus.HATE.name": "${subtype.creature}的死敌", + "core.bonus.HATE.name": "憎恨${subtype.creature}", "core.bonus.HATE.description": "对${subtype.creature}造成额外${val}%伤害", "core.bonus.HEALER.name": "治疗者", "core.bonus.HEALER.description": "可以治疗友军单位", diff --git a/launcher/translation/chinese.ts b/launcher/translation/chinese.ts index 11e156178..c80f1cfaa 100644 --- a/launcher/translation/chinese.ts +++ b/launcher/translation/chinese.ts @@ -639,267 +639,310 @@ Install successfully downloaded? CSettingsView + Off 关闭 - + Artificial Intelligence 人工智能 - + Interface Scaling 界面缩放 - + Neutral AI in battles 战场中立生物AI - + Enemy AI in battles 战场敌方玩家AI - + Additional repository 额外仓库 - + Downscaling Filter 图像缩小过滤器 - + Adventure Map Allies 冒险地图友方玩家 - + Online Lobby port 在线大厅端口 - + Autocombat AI in battles 自动战斗AI - + Sticks Sensitivity 摇杆灵敏度 - + Automatic (Linear) 自动(线性) - + Haptic Feedback 触觉反馈 - + Software Cursor 软件指针 - + + + Automatic 自动 - + + Mods Validation + 模组验证 + + + None - + xBRZ x2 xBRZ x2 - + xBRZ x3 xBRZ x3 - + xBRZ x4 xBRZ x4 - + + Full + 完备 + + + Use scalable fonts 使用可缩放字体 - + Online Lobby address 在线大厅地址 - + + Cursor Scaling + 指针缩放 + + + + Scalable + 可缩放字体 + + + + Miscellaneous + 杂项 + + + + Font Scaling (experimental) + 字体缩放(测试中) + + + + Original + 原始字体 + + + Upscaling Filter 图像放大过滤器 - + + Basic + 基本 + + + Use Relative Pointer Mode 使用相对指针模式 - + Nearest 最邻近 - + Linear 线性 - + Input - Touchscreen 输入 - 触屏 - + Adventure Map Enemies 冒险地图敌方玩家 - + 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 = 不限制) - + Framerate Limit 帧率限制 - + Autosave prefix 自动保存文件名前缀 - + Mouse Click Tolerance 鼠标点击灵敏度 - + Sticks Acceleration 摇杆加速度 - + empty = map name prefix 空 = 地图名称前缀 - + Refresh now 立即刷新 - + Default repository 默认仓库 - + Renderer 渲染器 @@ -909,7 +952,7 @@ Install successfully downloaded? 开启 - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -926,93 +969,93 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use 独占全屏模式 - 游戏会运行在一个覆盖全部屏幕的窗口,使用和你选择的分辨率。 - + Reserved screen area 保留屏幕区域 - + 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 安装 diff --git a/launcher/translation/czech.ts b/launcher/translation/czech.ts index f3a1225b1..1a47abdaf 100644 --- a/launcher/translation/czech.ts +++ b/launcher/translation/czech.ts @@ -634,267 +634,310 @@ Nainstalovat úspěšně stažené? CSettingsView + Off Vypnuto - + Artificial Intelligence Umělá inteligence - + 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 - + Downscaling Filter - + 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 - + Automatic (Linear) - + Haptic Feedback Zpětná odezva - + Software Cursor Softwarový kurzor - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address Adresa online předsíně - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter Filtr škálování - + + Basic + + + + Use Relative Pointer Mode Použít režim relativního ukazatele - + Nearest Nejbližší - + Linear Lineární - + Input - Touchscreen Vstup - dotyková obrazovka - + Adventure Map Enemies Nepřátelé na mapě světa - + 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) - + 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č @@ -904,7 +947,7 @@ Nainstalovat úspěšně stažené? Zapnuto - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -921,92 +964,92 @@ 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 - + 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 - + Not Installed Nenainstalováno - + Install Instalovat diff --git a/launcher/translation/english.ts b/launcher/translation/english.ts index 604274ac0..0114b4501 100644 --- a/launcher/translation/english.ts +++ b/launcher/translation/english.ts @@ -626,267 +626,310 @@ Install successfully downloaded? CSettingsView + Off - + 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 - + Automatic (Linear) - + Haptic Feedback - + Software Cursor - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address - - Upscaling Filter + + Cursor Scaling - - Use Relative Pointer Mode - - - - - Nearest - - - - - Linear - - - - - Input - Touchscreen - - - - - Adventure Map Enemies + + Scalable + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + + Upscaling Filter + + + + + Basic + + + + + Use Relative Pointer Mode + + + + + Nearest + + + + + Linear + + + + + Input - Touchscreen + + + + + Adventure Map Enemies + + + + Show Tutorial again - + Reset - + Network - + 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 - + Autosave limit (0 = off) - + Downscaling Filter - + Framerate Limit - + Autosave prefix - + Mouse Click Tolerance - + Sticks Acceleration - + empty = map name prefix - + Refresh now - + Default repository - + Renderer @@ -896,7 +939,7 @@ Install successfully downloaded? - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -907,92 +950,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 diff --git a/launcher/translation/french.ts b/launcher/translation/french.ts index 04ab48984..bd7f7dc30 100644 --- a/launcher/translation/french.ts +++ b/launcher/translation/french.ts @@ -639,12 +639,13 @@ Installer les téchargements réussis? CSettingsView + Off Désactivé - + Artificial Intelligence Intelligence Artificielle @@ -654,187 +655,229 @@ 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 Port de la salle d'attente en ligne - + Autocombat AI in battles IA de combat automatique dans les batailles - + Sticks Sensitivity Sensibilité au batons - + Automatic (Linear) Automatique (Linéaire) - + Haptic Feedback Retour Tactile - + Software Cursor Curseur Logiciel - + + + Automatic Automatique - + + Mods Validation + + + + None Aucun - + xBRZ x2 xBRZ x2 - + xBRZ x3 xBRZ x3 - + xBRZ x4 xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address Adresse de la salle d'attente en ligne - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter Filtre d'Agrandissement - + + Basic + + + + Use Relative Pointer Mode Utiliser le Mode de Pointeur Relatif - + Nearest Le plus Proche - + Linear Linéaire - + Input - Touchscreen Entrée - Écran tactile - + Network Réseau - + Downscaling Filter Filtre de Rétrécissement - + Show Tutorial again Remontrer le Didacticiel - + Reset Réinitialiser - + Audio Audio - + Relative Pointer Speed Vitesse de Pointeur Relatif - + Music Volume Volume de la Musique - + Ignore SSL errors Ignorer les erreurs SSL - + Input - Mouse Entrée - Sourie - + Long Touch Duration Durée de Touche Prolongée - + % % - + Controller Click Tolerance Tolérance au Clic de Contrôleur - + Touch Tap Tolerance Tolérance à la Frappe de Touche - + Input - Controller Entrée - Contrôleur - + Sound Volume Volume du Son - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -851,167 +894,167 @@ 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 - + Framerate Limit Limite de fréquence d"images - + 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 Tolérance au Clic de Sourie - + Sticks Acceleration Accelération de Bâton - + Refresh now Actualiser maintenant - + 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 diff --git a/launcher/translation/german.ts b/launcher/translation/german.ts index 659788841..90c01cbb3 100644 --- a/launcher/translation/german.ts +++ b/launcher/translation/german.ts @@ -634,267 +634,310 @@ Installation erfolgreich heruntergeladen? CSettingsView + Off Aus - + Artificial Intelligence Künstliche Intelligenz - + 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 - + Downscaling Filter - + 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 - + Automatic (Linear) - + Haptic Feedback Haptisches Feedback - + Software Cursor Software-Cursor - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address Adresse der Online-Lobby - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter Hochskalierungsfilter - + + Basic + + + + Use Relative Pointer Mode Relativen Zeigermodus verwenden - + Nearest Nearest - + Linear Linear - + Input - Touchscreen Eingabe - Touchscreen - + Adventure Map Enemies Abenteuerkarte Feinde - + Show Tutorial again Zeige Tutorial erneut - + Reset Zurücksetzen - + Network Netzwerk - + Audio 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) - + 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 @@ -904,7 +947,7 @@ Installation erfolgreich heruntergeladen? An - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -921,92 +964,92 @@ 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 - + 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 diff --git a/launcher/translation/polish.ts b/launcher/translation/polish.ts index c30a428c1..43b478497 100644 --- a/launcher/translation/polish.ts +++ b/launcher/translation/polish.ts @@ -634,267 +634,310 @@ Zainstalować pomyślnie pobrane? CSettingsView + Off Wyłączony - + Artificial Intelligence Sztuczna Inteligencja - + Interface Scaling Skala interfejsu - + Neutral AI in battles AI bitewne jednostek neutralnych - + Enemy AI in battles AI bitewne wrogów - + Additional repository Dodatkowe repozytorium - + Downscaling Filter - + 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 - + Automatic (Linear) - + Haptic Feedback Wibracje - + Software Cursor Kursor programowy - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address Adres lobby online - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter Filtr wyostrzający - + + Basic + + + + Use Relative Pointer Mode Użyj relatywnego trybu kursora - + Nearest Najbliższych - + Linear 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) - + 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 @@ -904,7 +947,7 @@ Zainstalować pomyślnie pobrane? Włączony - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -921,92 +964,92 @@ 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 - + 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 diff --git a/launcher/translation/portuguese.ts b/launcher/translation/portuguese.ts index 0f4108637..a95662eca 100644 --- a/launcher/translation/portuguese.ts +++ b/launcher/translation/portuguese.ts @@ -634,267 +634,310 @@ O download da instalação foi bem-sucedido? CSettingsView + Off Desativado - + Artificial Intelligence Inteligência artificial - + 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 - + Automatic (Linear) Automático (linear) - + Haptic Feedback Resposta tátil - + Software Cursor Cursor por software - + + + Automatic Automático - + + Mods Validation + + + + None Nenhum - + xBRZ x2 xBRZ x2 - + xBRZ x3 xBRZ x3 - + xBRZ x4 xBRZ x4 - - Use scalable fonts - Usar fontes escaláveis + + Full + - + + Use scalable fonts + Usar fontes escaláveis + + + Online Lobby address Endereço da sala de espera on-line - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter Filtro de aumento de escala - + + Basic + + + + Use Relative Pointer Mode Usar modo de ponteiro relativo - + Nearest Mais próximo - + Linear Linear - + Input - Touchscreen Entrada - tela de toque - + Adventure Map Enemies Inimigos do mapa de aventura - + Show Tutorial again Mostrar o tutorial novamente - + Reset Redefinir - + Network Linear - + Audio Á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) - + Downscaling Filter Filtro de redução de escala - + 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 @@ -904,7 +947,7 @@ O download da instalação foi bem-sucedido? Ativado - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -921,92 +964,92 @@ 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 - + 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 Salvamento automático - + 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 diff --git a/launcher/translation/russian.ts b/launcher/translation/russian.ts index b63ae0386..20a45663b 100644 --- a/launcher/translation/russian.ts +++ b/launcher/translation/russian.ts @@ -626,11 +626,12 @@ Install successfully downloaded? CSettingsView - + Interface Scaling + Off Отключено @@ -641,292 +642,334 @@ Install successfully downloaded? Включено - + Neutral AI in battles - + Enemy AI in battles - + Additional repository - + Check on startup Проверять при запуске - + Fullscreen Полноэкранный режим - + General Общее - + VCMI Language Язык VCMI - + Artificial Intelligence Искусственный интеллект - + Adventure Map Allies - + Refresh now - + Adventure Map Enemies - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Automatic (Linear) - + Haptic Feedback - + Software Cursor - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address - - Upscaling Filter + + Cursor Scaling - - Use Relative Pointer Mode - - - - - VSync - - - - - Nearest - - - - - Linear - - - - - Input - Touchscreen - - - - - Network - - - - - Downscaling Filter + + Scalable + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + + Upscaling Filter + + + + + Basic + + + + + Use Relative Pointer Mode + + + + + VSync + + + + + Nearest + + + + + Linear + + + + + Input - Touchscreen + + + + + Network + + + + + Downscaling Filter + + + + 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 - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -937,62 +980,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 Установить diff --git a/launcher/translation/spanish.ts b/launcher/translation/spanish.ts index 0b853743b..a1e9e19f6 100644 --- a/launcher/translation/spanish.ts +++ b/launcher/translation/spanish.ts @@ -633,267 +633,310 @@ Instalar lo correctamente descargado? CSettingsView + Off Desactivado - + Artificial Intelligence Inteligencia Artificial - + 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 - + Downscaling Filter - + Adventure Map Allies Aliados en el Mapa de aventuras - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Automatic (Linear) - + Haptic Feedback - + Software Cursor - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter - + + Basic + + + + Use Relative Pointer Mode - + Nearest - + Linear - + Input - Touchscreen - + Adventure Map Enemies Enemigos en el Mapa de aventuras - + Show Tutorial again - + Reset - + Network - + 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 Ventana - + Borderless fullscreen Ventana completa sin bordes - + Exclusive fullscreen Pantalla completa - + Autosave limit (0 = off) Límite de autosaves (0 = sin límite) - + 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 @@ -903,62 +946,62 @@ Instalar lo correctamente descargado? Activado - + 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 @@ -975,37 +1018,37 @@ Ventana sin bordes - el juego se ejecutará en una ventana que cubre completamen Pantalla completa - el juego cubrirá la totalidad de la pantalla y utilizará la resolución seleccionada. - + Show intro Mostrar introducción - + Check on startup Comprovar al inicio - + Active Activado - + Disabled Desactivado - + Enable Activar - + Not Installed No Instalado - + Install Instalar diff --git a/launcher/translation/swedish.ts b/launcher/translation/swedish.ts index deb1fd13b..f92834d02 100644 --- a/launcher/translation/swedish.ts +++ b/launcher/translation/swedish.ts @@ -634,12 +634,13 @@ Installation framgångsrikt nedladdad? CSettingsView + Off Inaktiverad - + Artificial Intelligence Artificiell intelligens @@ -649,187 +650,229 @@ Installation framgångsrikt nedladdad? Aktiverad - + Enemy AI in battles Fiendens AI i strider - + Default repository Standard-repositorie - + VSync Vertikal-synkronisering (VSync) - + Online Lobby port Port-numret till online-väntrummet - + Autocombat AI in battles Automatiska AI-strider - + Sticks Sensitivity Spak-känslighet - + Automatic (Linear) Automatisk (linjär) - + Haptic Feedback Haptisk återkoppling (vibrationer i kontrollen) - + Software Cursor Programvarustyrd muspekare - + + + Automatic Automatisk - + + Mods Validation + + + + None Inget - + xBRZ x2 xBRZ x2 - + xBRZ x3 xBRZ x3 - + xBRZ x4 xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address Adressen till online-väntrummet - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter Uppskalnings-filter - + + Basic + + + + Use Relative Pointer Mode Använd läge för relativ muspekare - + Nearest Närmast - + Linear Linjär - + Input - Touchscreen Ingång/indata - Pekskärm - + Network Nätverk - + Downscaling Filter Nerskalnings-filter - + Show Tutorial again Visa handledningen/övningsgenomgången igen - + Reset Återställ - + Audio Ljud - + Relative Pointer Speed Relativ pekarhastighet - + Music Volume Musikvolym - + Ignore SSL errors Ignorera SSL-fel - + Input - Mouse Ingång/indata - Mus - + Long Touch Duration Utökad beröringslängd - + % % - + Controller Click Tolerance Tolerans för klick på styrenhet - + Touch Tap Tolerance Tolerans för pektryck - + Input - Controller Ingång/indata - Kontroll - + Sound Volume Ljudvolym - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -846,167 +889,167 @@ Kantlöst fönsterläge - spelet körs i ett fönster som täcker hela din skär Exklusivt helskärmsläge - spelet kommer att täcka hela skärmen och använda den valda upplösningen. - + Windowed Fönsterläge - + Borderless fullscreen Kantlös helskärm - + Exclusive fullscreen Exklusiv helskärm - + Reserved screen area Reserverat skärmområde - + Neutral AI in battles Neutralt AI i strider - + Autosave limit (0 = off) Antal platser för automatisk-sparning (0 = inaktiverad) - + Adventure Map Enemies Fiender på äventyskartan - + Autosave prefix Prefix för automatisk-sparning - + empty = map name prefix tomt = kartnamnsprefix - + Interface Scaling Gränssnittsskalning - + Framerate Limit Gräns ​​för bildhastighet - + Renderer Renderingsmotor - + Heroes III Translation Heroes III - Översättning - + Adventure Map Allies Allierade på äventyrskartan - + Additional repository Ytterligare repositorier - + Check on startup Kontrollera vid uppstart - + Mouse Click Tolerance Musklickstolerans - + Sticks Acceleration Styrspaks-acceleration - + Refresh now Uppdatera nu - + Fullscreen Helskärm - + General Allmänt - + VCMI Language VCMI-språk - + Resolution Upplösning - + Autosave Auto-spara - + Display index Visa index - + Network port Nätverksport - + Video Video - + Show intro Visa intro - + Active Aktiv - + Disabled Inaktiverad - + Enable Aktivera - + Not Installed Inte installerad - + Install Installera @@ -1151,7 +1194,7 @@ Exklusivt helskärmsläge - spelet kommer att täcka hela skärmen och använda 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. - Om du äger Heroes III från GOG.com kan du ladda ner backup offline-installationsprogrammet från 'GOG.com'. VCMI kommer att importera Heroes III-data med hjälp av offline-installationsprogrammet. Offline-installationsprogrammet består av två delar, en '.exe'- och en '.bin'fil. Se till att ladda ner båda. + Om du äger Heroes III från GOG.com kan du ladda ner backup offline-installationsprogrammet från 'GOG.com'. VCMI kommer att importera Heroes III-data med hjälp av offline-installationsprogrammet. Offline-installationsprogrammet består av två delar, en '.exe'- och en '.bin'fil. Se till att ladda ner båda. @@ -1166,12 +1209,12 @@ Offline installer consists of two parts, .exe and .bin. Make sure you download b VCMI on Github - VCMI på 'Github' + VCMI på 'Github' VCMI on Discord - VCMI på 'Discord' + VCMI på 'Discord' @@ -1245,7 +1288,7 @@ Heroes® of Might and Magic® III HD stöds för närvarande inte! Optionally, you can install additional mods either now, or at any point later, using the VCMI Launcher - Du kan välja att installera ytterligare moddar, antingen nu eller vid ett senare tillfälle med hjälp av 'VCMI Launchern' + Du kan välja att installera ytterligare moddar, antingen nu eller vid ett senare tillfälle med hjälp av 'VCMI Launchern' diff --git a/launcher/translation/ukrainian.ts b/launcher/translation/ukrainian.ts index ddfe4a510..efdf8ea08 100644 --- a/launcher/translation/ukrainian.ts +++ b/launcher/translation/ukrainian.ts @@ -634,267 +634,310 @@ Install successfully downloaded? CSettingsView + Off Ні - + Artificial Intelligence Штучний інтелект - + Interface Scaling Масштабування інтерфейсу - + Neutral AI in battles Нейтральний ШІ в боях - + Enemy AI in battles Ворожий ШІ в боях - + Additional repository Додатковий репозиторій - + Downscaling Filter - + Adventure Map Allies Союзники на мапі пригод - + Online Lobby port Порт онлайн лобі - + Autocombat AI in battles ШІ автобою - + Sticks Sensitivity Чутливість стиків - + Automatic (Linear) - + Haptic Feedback - + Software Cursor Програмний курсор - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address Адреса онлайн-лобі - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter Фільтр масштабування - + + Basic + + + + Use Relative Pointer Mode Режим відносного вказівника - + Nearest Найближчий - + Linear Лінійний - + Input - Touchscreen Введення - Сенсорний екран - + Adventure Map Enemies Вороги на мапі пригод - + 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) Кількість автозбережень - + Framerate Limit Обмеження частоти кадрів - + Autosave prefix Префікс назв автозбережень - + Mouse Click Tolerance Допуск кліків миші - + Sticks Acceleration Прискорення стиків - + empty = map name prefix (використовувати назву карти) - + Refresh now Оновити зараз - + Default repository Стандартний репозиторій - + Renderer Рендерер @@ -904,7 +947,7 @@ Install successfully downloaded? Так - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -921,92 +964,92 @@ Fullscreen Exclusive Mode - game will cover entirety of your screen and will use Повноекранний ексклюзивний режим - гра займатиме весь екран і використовуватиме вибрану роздільну здатність. - + Reserved screen area Зарезервована зона екрану - + 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 Встановити diff --git a/launcher/translation/vietnamese.ts b/launcher/translation/vietnamese.ts index c5263d4e9..0f96f2242 100644 --- a/launcher/translation/vietnamese.ts +++ b/launcher/translation/vietnamese.ts @@ -626,267 +626,310 @@ Install successfully downloaded? CSettingsView + Off Tắt - + Artificial Intelligence Trí tuệ nhân tạo - + 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 - + Downscaling Filter - + Adventure Map Allies Máy liên minh ở bản đồ phiêu lưu - + Online Lobby port - + Autocombat AI in battles - + Sticks Sensitivity - + Automatic (Linear) - + Haptic Feedback - + Software Cursor - + + + Automatic - + + Mods Validation + + + + None - + xBRZ x2 - + xBRZ x3 - + xBRZ x4 - + + Full + + + + Use scalable fonts - + Online Lobby address - + + Cursor Scaling + + + + + Scalable + + + + + Miscellaneous + + + + + Font Scaling (experimental) + + + + + Original + + + + Upscaling Filter - + + Basic + + + + Use Relative Pointer Mode - + Nearest - + Linear - + Input - Touchscreen - + Adventure Map Enemies Máy đối thủ ở bản đồ phiêu lưu - + Show Tutorial again - + Reset - + Network - + 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 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) - + 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 @@ -896,7 +939,7 @@ Install successfully downloaded? Bật - + Select display mode for game Windowed - game will run inside a window that covers part of your screen @@ -913,92 +956,92 @@ 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 - + 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 From d4d3ddf6850ddc945728577ff1a65af38605a291 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sat, 12 Oct 2024 13:33:46 +0300 Subject: [PATCH 15/69] fused artifacts --- client/ArtifactsUIController.cpp | 2 +- .../Entities_Format/Artifact_Format.md | 3 +++ lib/CArtHandler.cpp | 23 ++++++++++++++++--- lib/CArtHandler.h | 7 +++++- lib/CArtifactInstance.cpp | 5 ++++ lib/CArtifactInstance.h | 1 + lib/networkPacks/NetPacksLib.cpp | 16 ++++++++----- lib/networkPacks/PacksForClient.h | 6 ++--- server/CGameHandler.cpp | 5 +++- 9 files changed, 53 insertions(+), 15 deletions(-) diff --git a/client/ArtifactsUIController.cpp b/client/ArtifactsUIController.cpp index 73461a58a..30374ebc2 100644 --- a/client/ArtifactsUIController.cpp +++ b/client/ArtifactsUIController.cpp @@ -102,7 +102,7 @@ bool ArtifactsUIController::askToDisassemble(const CGHeroInstance * hero, const if(hero->tempOwner != LOCPLINT->playerID) return false; - if(art->isCombined()) + if(art->hasParts()) { if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1)) return false; diff --git a/docs/modders/Entities_Format/Artifact_Format.md b/docs/modders/Entities_Format/Artifact_Format.md index 928496dc7..83b1adca2 100644 --- a/docs/modders/Entities_Format/Artifact_Format.md +++ b/docs/modders/Entities_Format/Artifact_Format.md @@ -67,6 +67,9 @@ In order to make functional artifact you also need: "artifact2", "artifact3" ], + + // Optional, by default is false. Set to true if components are supposed to be fused. + "fusedComponents" : true, // Creature id to use on battle field. If set, this artifact is war machine "warMachine" : "some.creature" diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 07b83dec3..f96e17f83 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -61,6 +61,21 @@ const std::vector & CCombinedArtifact::getPartOf() const return partOf; } +void CCombinedArtifact::setFused(bool isFused) +{ + fused = isFused; +} + +bool CCombinedArtifact::isFused() const +{ + return fused; +} + +bool CCombinedArtifact::hasParts() const +{ + return isCombined() && !isFused(); +} + bool CScrollArtifact::isScroll() const { return static_cast(this)->getId() == ArtifactID::SPELL_SCROLL; @@ -203,7 +218,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b auto artCanBePutAt = [this, simpleArtCanBePutAt](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool { - if(isCombined()) + if(hasParts()) { if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved)) return false; @@ -606,11 +621,11 @@ void CArtHandler::loadType(CArtifact * art, const JsonNode & node) const void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node) { - if (!node["components"].isNull()) + if(!node["components"].isNull()) { for(const auto & component : node["components"].Vector()) { - VLC->identifiers()->requestIdentifier("artifact", component, [=](si32 id) + VLC->identifiers()->requestIdentifier("artifact", component, [this, art](int32_t id) { // when this code is called both combinational art as well as component are loaded // so it is safe to access any of them @@ -619,6 +634,8 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node) }); } } + if(!node["fusedComponents"].isNull()) + art->setFused(node["fusedComponents"].Bool()); } void CArtHandler::makeItCreatureArt(CArtifact * a, bool onlyCreature) diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index e82f43147..f0bf7d8af 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -46,14 +46,19 @@ namespace ArtBearer class DLL_LINKAGE CCombinedArtifact { protected: - CCombinedArtifact() = default; + CCombinedArtifact() : fused(false) {}; std::vector constituents; // Artifacts IDs a combined artifact consists of, or nullptr. std::vector partOf; // Reverse map of constituents - combined arts that include this art + bool fused; + public: bool isCombined() const; const std::vector & getConstituents() const; const std::vector & getPartOf() const; + void setFused(bool isFused); + bool isFused() const; + bool hasParts() const; }; class DLL_LINKAGE CScrollArtifact diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 6f191e46b..f65e6d95b 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -44,6 +44,11 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c return false; } +bool CCombinedArtifactInstance::hasParts() const +{ + return !partsInfo.empty(); +} + const std::vector & CCombinedArtifactInstance::getPartsInfo() const { return partsInfo; diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index f679f8b44..6ff0bdbe0 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -38,6 +38,7 @@ public: void addPart(CArtifactInstance * art, const ArtifactPosition & slot); // Checks if supposed part inst is part of this combined art inst bool isPart(const CArtifactInstance * supposedPart) const; + bool hasParts() const; const std::vector & getPartsInfo() const; void addPlacementMap(const CArtifactSet::ArtPlacementMap & placementMap); diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 6ea83ab8f..f44e6411e 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1806,6 +1806,7 @@ void AssembledArtifact::applyGs(CGameState *gs) assert(hero); const auto transformedArt = hero->getArt(al.slot); assert(transformedArt); + const auto builtArt = artId.toArtifact(); assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(hero, transformedArt->getTypeId()), [=](const CArtifact * art)->bool { return art->getId() == builtArt->getId(); @@ -1832,7 +1833,7 @@ void AssembledArtifact::applyGs(CGameState *gs) // Find a slot for combined artifact al.slot = transformedArtSlot; - for(const auto slot : slotsInvolved) + for(const auto & slot : slotsInvolved) { if(ArtifactUtils::isSlotEquipment(transformedArtSlot)) { @@ -1855,15 +1856,18 @@ void AssembledArtifact::applyGs(CGameState *gs) } // Delete parts from hero - for(const auto slot : slotsInvolved) + for(const auto & slot : slotsInvolved) { const auto constituentInstance = hero->getArt(slot); gs->map->removeArtifactInstance(*hero, slot); - if(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot) - combinedArt->addPart(constituentInstance, slot); - else - combinedArt->addPart(constituentInstance, ArtifactPosition::PRE_FIRST); + if(!combinedArt->artType->isFused()) + { + if(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot) + combinedArt->addPart(constituentInstance, slot); + else + combinedArt->addPart(constituentInstance, ArtifactPosition::PRE_FIRST); + } } // Put new combined artifacts diff --git a/lib/networkPacks/PacksForClient.h b/lib/networkPacks/PacksForClient.h index b9f678ba6..0413113dc 100644 --- a/lib/networkPacks/PacksForClient.h +++ b/lib/networkPacks/PacksForClient.h @@ -1108,8 +1108,8 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack struct DLL_LINKAGE AssembledArtifact : CArtifactOperationPack { - ArtifactLocation al; //where assembly will be put - const CArtifact * builtArt; + ArtifactLocation al; + ArtifactID artId; void applyGs(CGameState * gs) override; @@ -1118,7 +1118,7 @@ struct DLL_LINKAGE AssembledArtifact : CArtifactOperationPack template void serialize(Handler & h) { h & al; - h & builtArt; + h & artId; } }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1f9549fa0..ab933a4f8 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2913,7 +2913,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a AssembledArtifact aa; aa.al = dstLoc; - aa.builtArt = combinedArt; + aa.artId = assembleTo; sendAndApply(aa); } else @@ -2921,6 +2921,9 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a if(!destArtifact->isCombined()) COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble is not a combined artifact!"); + if(!destArtifact->hasParts()) + COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble is fused combined artifact!"); + if(ArtifactUtils::isSlotBackpack(artifactSlot) && !ArtifactUtils::isBackpackFreeSlots(hero, destArtifact->artType->getConstituents().size() - 1)) COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble but backpack is full!"); From 11eaed9fef7705c4935df7ebdd1eb48fa103eab1 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sat, 12 Oct 2024 23:01:14 +0200 Subject: [PATCH 16/69] code review --- client/adventureMap/AdventureMapShortcuts.cpp | 26 ++++++------------- lib/CGameInfoCallback.cpp | 11 ++++++++ lib/CGameInfoCallback.h | 2 ++ 3 files changed, 21 insertions(+), 18 deletions(-) diff --git a/client/adventureMap/AdventureMapShortcuts.cpp b/client/adventureMap/AdventureMapShortcuts.cpp index f3ab04933..d5c5ce321 100644 --- a/client/adventureMap/AdventureMapShortcuts.cpp +++ b/client/adventureMap/AdventureMapShortcuts.cpp @@ -467,29 +467,19 @@ void AdventureMapShortcuts::search(bool next) { // get all relevant objects std::vector visitableObjInstances; - int3 mapSizes = LOCPLINT->cb->getMapSize(); - for(int x = 0; x < mapSizes.x; x++) - for(int y = 0; y < mapSizes.y; y++) - for(int z = 0; z < mapSizes.z; z++) - for(auto & obj : LOCPLINT->cb->getVisitableObjs(int3(x, y, z), false)) - if(obj->ID != MapObjectID::MONSTER && obj->ID != MapObjectID::EVENT && obj->ID != MapObjectID::HERO) - visitableObjInstances.push_back(obj->id); + for(auto & obj : LOCPLINT->cb->getAllVisitableObjs()) + if(obj->ID != MapObjectID::MONSTER && obj->ID != MapObjectID::HERO && obj->ID != MapObjectID::TOWN) + visitableObjInstances.push_back(obj->id); - // count of elements for each group + // count of elements for each group (map is already sorted) std::map mapObjCount; for(auto & obj : visitableObjInstances) - mapObjCount[{ VLC->objtypeh->getObjectName(LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex()) }]++; + mapObjCount[{ LOCPLINT->cb->getObjInstance(obj)->getObjectName() }]++; - // sort by name + // convert to vector for indexed access std::vector> textCountList; for (auto itr = mapObjCount.begin(); itr != mapObjCount.end(); ++itr) textCountList.push_back(*itr); - std::sort(textCountList.begin(), textCountList.end(), - [=](std::pair& a, std::pair& b) - { - return a.first < b.first; - } - ); // get pos of last selection int lastSel = 0; @@ -510,7 +500,7 @@ void AdventureMapShortcuts::search(bool next) // filter for matching objects std::vector selVisitableObjInstances; for(auto & obj : visitableObjInstances) - if(selObj == VLC->objtypeh->getObjectName(LOCPLINT->cb->getObjInstance(obj)->getObjGroupIndex(), LOCPLINT->cb->getObjInstance(obj)->getObjTypeIndex())) + if(selObj == LOCPLINT->cb->getObjInstance(obj)->getObjectName()) selVisitableObjInstances.push_back(obj); if(searchPos + 1 < selVisitableObjInstances.size() && searchLast == selObj) @@ -520,7 +510,7 @@ void AdventureMapShortcuts::search(bool next) auto objInst = LOCPLINT->cb->getObjInstance(selVisitableObjInstances[searchPos]); owner.centerOnObject(objInst); - searchLast = VLC->objtypeh->getObjectName(objInst->getObjGroupIndex(), objInst->getObjTypeIndex()); + searchLast = objInst->getObjectName(); }; if(next) diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index 8e404e34c..9837848db 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -479,6 +479,17 @@ std::vector CGameInfoCallback::getVisitableObjs(int3 return ret; } + +std::vector> CGameInfoCallback::getAllVisitableObjs() const +{ + std::vector> ret; + for(auto & obj : gs->map->objects) + if(obj->isVisitable() && obj->ID != Obj::EVENT && getTile(obj->pos, false)) + ret.push_back(obj); + + return ret; +} + const CGObjectInstance * CGameInfoCallback::getTopObj (int3 pos) const { return vstd::backOrNull(getVisitableObjs(pos)); diff --git a/lib/CGameInfoCallback.h b/lib/CGameInfoCallback.h index 91c51b5a7..25f15d53e 100644 --- a/lib/CGameInfoCallback.h +++ b/lib/CGameInfoCallback.h @@ -11,6 +11,7 @@ #include "int3.h" #include "ResourceSet.h" // for Res +#include "ConstTransitivePtr.h" #define ASSERT_IF_CALLED_WITH_PLAYER if(!getPlayerID()) {logGlobal->error(BOOST_CURRENT_FUNCTION); assert(0);} @@ -189,6 +190,7 @@ public: const CGObjectInstance * getObj(ObjectInstanceID objid, bool verbose = true) const override; virtual std::vector getBlockingObjs(int3 pos)const; std::vector getVisitableObjs(int3 pos, bool verbose = true) const override; + std::vector> getAllVisitableObjs() const; virtual std::vector getFlaggableObjects(int3 pos) const; virtual const CGObjectInstance * getTopObj (int3 pos) const; virtual PlayerColor getOwner(ObjectInstanceID heroID) const; From f7e3641c04db1d4abf38467ab8e487bfc48eaca8 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sat, 12 Oct 2024 23:21:26 +0200 Subject: [PATCH 17/69] fix shortcut bug; add center of selected item --- client/windows/GUIClasses.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 7727afd56..d6ceea6bf 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -1487,6 +1487,9 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, std::share images(images) { OBJECT_CONSTRUCTION; + + addUsedEvents(KEYBOARD); + items.reserve(_items.size()); for(int id : _items) @@ -1494,7 +1497,7 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, std::share itemsVisible = items; init(titleWidget_, _title, _descr, searchBoxEnabled); - list->scrollTo(initialSelection); + list->scrollTo(initialSelection - 4); // -4 is for centering (list have 9 elements) } CObjectListWindow::CObjectListWindow(const std::vector & _items, std::shared_ptr titleWidget_, std::string _title, std::string _descr, std::function Callback, size_t initialSelection, std::vector> images, bool searchBoxEnabled) @@ -1504,6 +1507,9 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, st images(images) { OBJECT_CONSTRUCTION; + + addUsedEvents(KEYBOARD); + items.reserve(_items.size()); for(size_t i=0; i<_items.size(); i++) @@ -1511,7 +1517,7 @@ CObjectListWindow::CObjectListWindow(const std::vector & _items, st itemsVisible = items; init(titleWidget_, _title, _descr, searchBoxEnabled); - list->scrollTo(initialSelection); + list->scrollTo(initialSelection - 4); // -4 is for centering (list have 9 elements) } void CObjectListWindow::init(std::shared_ptr titleWidget_, std::string _title, std::string _descr, bool searchBoxEnabled) @@ -1636,7 +1642,7 @@ void CObjectListWindow::keyPressed(EShortcut key) } vstd::abetween(sel, 0, itemsVisible.size()-1); - list->scrollTo(sel); + list->scrollTo(sel - 4); // -4 is for centering (list have 9 elements) changeSelection(sel); } From 640ef0ea1944fccd8a03542779b0354e6d390451 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C5=81ukasz=20Zaj=C4=85c?= <4561094+ToRRent1812@users.noreply.github.com> Date: Sat, 12 Oct 2024 23:57:58 +0200 Subject: [PATCH 18/69] Update polish.json Added new stuff --- Mods/vcmi/config/vcmi/polish.json | 25 +++++++++++++++++++++++-- 1 file changed, 23 insertions(+), 2 deletions(-) diff --git a/Mods/vcmi/config/vcmi/polish.json b/Mods/vcmi/config/vcmi/polish.json index 2f8d0ce87..7f8840169 100644 --- a/Mods/vcmi/config/vcmi/polish.json +++ b/Mods/vcmi/config/vcmi/polish.json @@ -12,6 +12,9 @@ "vcmi.adventureMap.monsterThreat.levels.9" : "Przytłaczający", "vcmi.adventureMap.monsterThreat.levels.10" : "Śmiertelny", "vcmi.adventureMap.monsterThreat.levels.11" : "Nie do pokonania", + "vcmi.adventureMap.monsterLevel" : "\n\n%Jednostka %ATTACK_TYPE %LEVEL poziomu z miasta %TOWN", + "vcmi.adventureMap.monsterMeleeType" : "Walcząca wręcz", + "vcmi.adventureMap.monsterRangedType" : "Dystansowa", "vcmi.adventureMap.confirmRestartGame" : "Czy na pewno chcesz zrestartować grę?", "vcmi.adventureMap.noTownWithMarket" : "Brak dostępnego targowiska!", @@ -58,6 +61,13 @@ "vcmi.spellBook.search" : "szukaj...", + "vcmi.spellResearch.canNotAfford" : "Nie stać Cię na zastąpienie {%SPELL1} przez {%SPELL2}, ale za to możesz odrzucić ten czar i kontynuować badania.", + "vcmi.spellResearch.comeAgain" : "Badania zostały już przeprowadzone dzisiaj. Wróć jutro.", + "vcmi.spellResearch.pay" : "Czy chcesz zastąpić {%SPELL1} czarem {%SPELL2}? Czy odrzucić ten czar i kontynuować badania?", + "vcmi.spellResearch.research" : "Zamień zaklęcia", + "vcmi.spellResearch.skip" : "Kontynuuj badania", + "vcmi.spellResearch.abort" : "Anuluj", + "vcmi.mainMenu.serverConnecting" : "Łączenie...", "vcmi.mainMenu.serverAddressEnter" : "Wprowadź adres:", "vcmi.mainMenu.serverConnectionFailed" : "Połączenie nie powiodło się", @@ -142,6 +152,7 @@ "vcmi.client.errors.invalidMap" : "{Błędna mapa lub kampania}\n\nNie udało się stworzyć gry! Wybrana mapa lub kampania jest niepoprawna lub uszkodzona. Powód:\n%s", "vcmi.client.errors.missingCampaigns" : "{Brakujące pliki gry}\n\nPliki kampanii nie zostały znalezione! Możliwe że używasz niekompletnych lub uszkodzonych plików Heroes 3. Spróbuj ponownej instalacji plików gry.", "vcmi.server.errors.disconnected" : "{Błąd sieciowy}\n\nUtracono połączenie z serwerem!", + "vcmi.server.errors.playerLeft" : "{Rozłączenie z graczem}\n\n%s opuścił rozgrywkę!", //%s -> player color "vcmi.server.errors.existingProcess" : "Inny proces 'vcmiserver' został już uruchomiony, zakończ go nim przejdziesz dalej", "vcmi.server.errors.modsToEnable" : "{Następujące mody są wymagane do wczytania gry}", "vcmi.server.errors.modsToDisable" : "{Następujące mody muszą zostać wyłączone}", @@ -235,8 +246,10 @@ "vcmi.adventureOptions.borderScroll.help" : "{Przewijanie na brzegu mapy}\n\nPrzewijanie mapy przygody gdy kursor najeżdża na brzeg okna gry. Może być wyłączone poprzez przytrzymanie klawisza CTRL.", "vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Zarządzanie armią w panelu informacyjnym", "vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Zarządzanie armią w panelu informacyjnym}\n\nPozwala zarządzać jednostkami w panelu informacyjnym, zamiast przełączać między domyślnymi informacjami.", - "vcmi.adventureOptions.leftButtonDrag.hover" : "Przeciąganie mapy lewym kliknięciem", + "vcmi.adventureOptions.leftButtonDrag.hover" : "Przeciąganie lewym", "vcmi.adventureOptions.leftButtonDrag.help" : "{Przeciąganie mapy lewym kliknięciem}\n\nUmożliwia przesuwanie mapy przygody poprzez przeciąganie myszy z wciśniętym lewym przyciskiem.", + "vcmi.adventureOptions.rightButtonDrag.hover" : "Przeciąganie prawym", + "vcmi.adventureOptions.rightButtonDrag.help" : "{Przeciąganie mapy prawym kliknięciem}\n\nUmożliwia przesuwanie mapy przygody poprzez przeciąganie myszy z wciśniętym prawym przyciskiem.", "vcmi.adventureOptions.smoothDragging.hover" : "'Pływające' przeciąganie mapy", "vcmi.adventureOptions.smoothDragging.help" : "{'Pływające' przeciąganie mapy}\n\nPrzeciąganie mapy następuje ze stopniowo zanikającym przyspieszeniem.", "vcmi.adventureOptions.skipAdventureMapAnimations.hover" : "Pomiń efekty zanikania", @@ -337,6 +350,12 @@ "vcmi.heroWindow.openCommander.help" : "Wyświetla informacje o dowódcy przynależącym do tego bohatera", "vcmi.heroWindow.openBackpack.hover" : "Otwórz okno sakwy", "vcmi.heroWindow.openBackpack.help" : "Otwiera okno pozwalające łatwiej zarządzać artefaktami w sakwie", + "vcmi.heroWindow.sortBackpackByCost.hover" : "Sortuj wg. wartości", + "vcmi.heroWindow.sortBackpackByCost.help" : "Sortuj artefakty w sakwie według wartości", + "vcmi.heroWindow.sortBackpackBySlot.hover" : "Sortuj wg. miejsc", + "vcmi.heroWindow.sortBackpackBySlot.help" : "Sortuj artefakty w sakwie według umiejscowienia na ciele", + "vcmi.heroWindow.sortBackpackByClass.hover" : "Sortuj wg. jakości", + "vcmi.heroWindow.sortBackpackByClass.help" : "Sortuj artefakty w sakwie według jakości: Skarb, Pomniejszy, Potężny, Relikt", "vcmi.tavernWindow.inviteHero" : "Zaproś bohatera", @@ -663,5 +682,7 @@ "core.bonus.WIDE_BREATH.name": "Szerokie zionięcie", "core.bonus.WIDE_BREATH.description": "Szeroki atak zionięciem (wiele heksów)", "core.bonus.DISINTEGRATE.name": "Rozpadanie", - "core.bonus.DISINTEGRATE.description": "Po śmierci nie pozostaje żaden trup" + "core.bonus.DISINTEGRATE.description": "Po śmierci nie pozostaje żaden trup", + "core.bonus.INVINCIBLE.name": "Niezwyciężony", + "core.bonus.INVINCIBLE.description": "Nic nie może mieć na niego wpływu" } From 4bdc5031866cd909f0fcdbd8044a3e4a010b86ea Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Oct 2024 08:28:37 +0000 Subject: [PATCH 19/69] Workaround for prison hero reset on loading map in editor --- mapeditor/mapcontroller.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index a30a90aa8..fc68f4602 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -151,8 +151,8 @@ void MapController::repairMap(CMap * map) const if(obj->ID == Obj::PRISON) { nih->typeName = "prison"; - nih->subTypeName = "prison"; - nih->subID = 0; + //nih->subTypeName = "prison"; + //nih->subID = 0; } if(nih->ID == Obj::HERO) //not prison nih->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); From 31095248ab49ac74f5ad740ba886f5c856e10261 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Oct 2024 13:05:50 +0000 Subject: [PATCH 20/69] Removed typeName and subtypeName properties from CGObjectInstance --- AI/Nullkiller/Goals/CaptureObject.h | 2 +- AI/Nullkiller/Goals/ExecuteHeroChain.cpp | 2 +- AI/Nullkiller/Pathfinding/Actors.cpp | 2 +- .../AObjectTypeHandler.cpp | 2 -- lib/mapObjects/CGObjectInstance.cpp | 10 +++++++++ lib/mapObjects/CGObjectInstance.h | 13 +++++++---- lib/mapping/CMap.cpp | 2 +- lib/rmg/modificators/ObstaclePlacer.cpp | 2 +- lib/serializer/ESerializationVersion.h | 3 ++- mapeditor/inspector/inspector.cpp | 2 -- mapeditor/mapcontroller.cpp | 22 +------------------ test/map/MapComparer.cpp | 4 ++-- 12 files changed, 29 insertions(+), 37 deletions(-) diff --git a/AI/Nullkiller/Goals/CaptureObject.h b/AI/Nullkiller/Goals/CaptureObject.h index e219e37ec..2073cd2fe 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->typeName; + name = obj->getTypeName(); } bool operator==(const CaptureObject & other) const override; diff --git a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp index 8fe4851b2..a12489e99 100644 --- a/AI/Nullkiller/Goals/ExecuteHeroChain.cpp +++ b/AI/Nullkiller/Goals/ExecuteHeroChain.cpp @@ -30,7 +30,7 @@ ExecuteHeroChain::ExecuteHeroChain(const AIPath & path, const CGObjectInstance * #if NKAI_TRACE_LEVEL >= 1 targetName = obj->getObjectName() + tile.toString(); #else - targetName = obj->typeName + tile.toString(); + targetName = obj->getTypeName() + tile.toString(); #endif } else diff --git a/AI/Nullkiller/Pathfinding/Actors.cpp b/AI/Nullkiller/Pathfinding/Actors.cpp index ae6b6446e..145283d48 100644 --- a/AI/Nullkiller/Pathfinding/Actors.cpp +++ b/AI/Nullkiller/Pathfinding/Actors.cpp @@ -440,7 +440,7 @@ int DwellingActor::getInitialTurn(bool waitForGrowth, int dayOfWeek) std::string DwellingActor::toString() const { - return dwelling->typeName + dwelling->visitablePos().toString(); + return dwelling->getTypeName() + dwelling->visitablePos().toString(); } CCreatureSet * DwellingActor::getDwellingCreatures(const CGDwelling * dwelling, bool waitForGrowth) diff --git a/lib/mapObjectConstructors/AObjectTypeHandler.cpp b/lib/mapObjectConstructors/AObjectTypeHandler.cpp index c431900aa..d842d9953 100644 --- a/lib/mapObjectConstructors/AObjectTypeHandler.cpp +++ b/lib/mapObjectConstructors/AObjectTypeHandler.cpp @@ -133,8 +133,6 @@ void AObjectTypeHandler::preInitObject(CGObjectInstance * obj) const { obj->ID = Obj(type); obj->subID = subtype; - obj->typeName = typeName; - obj->subTypeName = getJsonKey(); obj->blockVisit = blockVisit; obj->removable = removable; } diff --git a/lib/mapObjects/CGObjectInstance.cpp b/lib/mapObjects/CGObjectInstance.cpp index aa902a452..5c4da7da0 100644 --- a/lib/mapObjects/CGObjectInstance.cpp +++ b/lib/mapObjects/CGObjectInstance.cpp @@ -192,6 +192,16 @@ TObjectTypeHandler CGObjectInstance::getObjectHandler() const return VLC->objtypeh->getHandlerFor(ID, subID); } +std::string CGObjectInstance::getTypeName() const +{ + return getObjectHandler()->getTypeName(); +} + +std::string CGObjectInstance::getSubtypeName() const +{ + return getObjectHandler()->getSubTypeName(); +} + void CGObjectInstance::setPropertyDer( ObjProperty what, ObjPropertyID identifier ) {} diff --git a/lib/mapObjects/CGObjectInstance.h b/lib/mapObjects/CGObjectInstance.h index b5fdd7142..8df5bbba1 100644 --- a/lib/mapObjects/CGObjectInstance.h +++ b/lib/mapObjects/CGObjectInstance.h @@ -43,8 +43,6 @@ public: int3 pos; std::string instanceName; - std::string typeName; - std::string subTypeName; CGObjectInstance(IGameCallback *cb); ~CGObjectInstance() override; @@ -52,6 +50,9 @@ public: MapObjectID getObjGroupIndex() const override; MapObjectSubID getObjTypeIndex() const override; + std::string getTypeName() const; + std::string getSubtypeName() const; + /// "center" tile from which the sight distance is calculated int3 getSightCenter() const; /// If true hero can visit this object only from neighbouring tiles and can't stand on this object @@ -142,8 +143,12 @@ public: template void serialize(Handler &h) { h & instanceName; - h & typeName; - h & subTypeName; + if (h.version < Handler::Version::REMOVE_OBJECT_TYPENAME) + { + std::string unused; + h & unused; + h & unused; + } h & pos; h & ID; subID.serializeIdentifier(h, ID); diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 57e3a4c24..bf16f913b 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -608,7 +608,7 @@ void CMap::setUniqueInstanceName(CGObjectInstance * obj) auto uid = uidCounter++; boost::format fmt("%s_%d"); - fmt % obj->typeName % uid; + fmt % obj->getTypeName() % uid; obj->instanceName = fmt.str(); } diff --git a/lib/rmg/modificators/ObstaclePlacer.cpp b/lib/rmg/modificators/ObstaclePlacer.cpp index 456ddbeb0..5447a256e 100644 --- a/lib/rmg/modificators/ObstaclePlacer.cpp +++ b/lib/rmg/modificators/ObstaclePlacer.cpp @@ -153,7 +153,7 @@ void ObstaclePlacer::postProcess(const rmg::Object & object) riverManager = zone.getModificator(); if(riverManager) { - const auto objTypeName = object.instances().front()->object().typeName; + const auto objTypeName = object.instances().front()->object().getTypeName(); if(objTypeName == "mountain") riverManager->riverSource().unite(object.getArea()); else if(objTypeName == "lake") diff --git a/lib/serializer/ESerializationVersion.h b/lib/serializer/ESerializationVersion.h index d0fe579e4..7b4270bc9 100644 --- a/lib/serializer/ESerializationVersion.h +++ b/lib/serializer/ESerializationVersion.h @@ -64,6 +64,7 @@ enum class ESerializationVersion : int32_t SPELL_RESEARCH, // 865 - spell research LOCAL_PLAYER_STATE_DATA, // 866 - player state contains arbitrary client-side data REMOVE_TOWN_PTR, // 867 - removed pointer to CTown from CGTownInstance + REMOVE_OBJECT_TYPENAME, // 868 - remove typename from CGObjectInstance - CURRENT = REMOVE_TOWN_PTR + CURRENT = REMOVE_OBJECT_TYPENAME }; diff --git a/mapeditor/inspector/inspector.cpp b/mapeditor/inspector/inspector.cpp index 4ad9c5eaf..d8daa2162 100644 --- a/mapeditor/inspector/inspector.cpp +++ b/mapeditor/inspector/inspector.cpp @@ -470,8 +470,6 @@ void Inspector::updateProperties() addProperty("ID", obj->ID.getNum()); addProperty("SubID", obj->subID); addProperty("InstanceName", obj->instanceName); - addProperty("TypeName", obj->typeName); - addProperty("SubTypeName", obj->subTypeName); if(obj->ID != Obj::HERO_PLACEHOLDER && !dynamic_cast(obj)) { diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index fc68f4602..8aa581a36 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -112,13 +112,6 @@ void MapController::repairMap(CMap * map) const allImpactedObjects.insert(allImpactedObjects.end(), map->predefinedHeroes.begin(), map->predefinedHeroes.end()); for(auto obj : allImpactedObjects) { - //setup proper names (hero name will be fixed later - if(obj->ID != Obj::HERO && obj->ID != Obj::PRISON && (obj->typeName.empty() || obj->subTypeName.empty())) - { - auto handler = VLC->objtypeh->getHandlerFor(obj->ID, obj->subID); - obj->typeName = handler->getTypeName(); - obj->subTypeName = handler->getSubTypeName(); - } //fix flags if(obj->getOwner() == PlayerColor::UNFLAGGABLE) { @@ -142,18 +135,7 @@ void MapController::repairMap(CMap * map) const auto const & type = VLC->heroh->objects[nih->subID]; assert(type->heroClass); - //TODO: find a way to get proper type name - if(obj->ID == Obj::HERO) - { - nih->typeName = "hero"; - nih->subTypeName = type->heroClass->getJsonKey(); - } - if(obj->ID == Obj::PRISON) - { - nih->typeName = "prison"; - //nih->subTypeName = "prison"; - //nih->subID = 0; - } + if(nih->ID == Obj::HERO) //not prison nih->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, type->heroClass->getIndex())->getTemplates().front(); //fix spellbook @@ -568,8 +550,6 @@ bool MapController::canPlaceObject(int level, CGObjectInstance * newObj, QString if(newObj->ID == Obj::GRAIL && objCounter >= 1) //special case for grail { - auto typeName = QString::fromStdString(newObj->typeName); - auto subTypeName = QString::fromStdString(newObj->subTypeName); error = QObject::tr("There can only be one grail object on the map."); return false; //maplimit reached } diff --git a/test/map/MapComparer.cpp b/test/map/MapComparer.cpp index 28ace85c2..8d1744520 100644 --- a/test/map/MapComparer.cpp +++ b/test/map/MapComparer.cpp @@ -203,8 +203,8 @@ void MapComparer::compareObject(const CGObjectInstance * actual, const CGObjectI EXPECT_EQ(actual->instanceName, expected->instanceName); EXPECT_EQ(typeid(actual).name(), typeid(expected).name());//todo: remove and use just comparison - std::string actualFullID = boost::str(boost::format("%s(%d)|%s(%d) %d") % actual->typeName % actual->ID % actual->subTypeName % actual->subID % actual->tempOwner); - std::string expectedFullID = boost::str(boost::format("%s(%d)|%s(%d) %d") % expected->typeName % expected->ID % expected->subTypeName % expected->subID % expected->tempOwner); + std::string actualFullID = boost::str(boost::format("(%d)|(%d) %d") % actual->ID % actual->subID % actual->tempOwner); + std::string expectedFullID = boost::str(boost::format("(%d)|(%d) %d") % expected->ID % expected->subID % expected->tempOwner); EXPECT_EQ(actualFullID, expectedFullID); From 184d8de82e16ae8f2568c9fa9305e4e246a422ee Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Oct 2024 13:06:07 +0000 Subject: [PATCH 21/69] Fix typo in assertion --- client/PlayerLocalState.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/client/PlayerLocalState.cpp b/client/PlayerLocalState.cpp index 519c39c94..2b347cb27 100644 --- a/client/PlayerLocalState.cpp +++ b/client/PlayerLocalState.cpp @@ -347,7 +347,7 @@ void PlayerLocalState::deserialize(const JsonNode & source) { // this method must be called after player state has been initialized assert(currentSelection != nullptr); - assert(!ownedTowns.empty() || wanderingHeroes.empty()); + assert(!ownedTowns.empty() || !wanderingHeroes.empty()); auto oldHeroes = wanderingHeroes; auto oldTowns = ownedTowns; From ad7f0416a70b7118f651ed2f9a134bd2779c0663 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Sun, 13 Oct 2024 13:06:31 +0000 Subject: [PATCH 22/69] Added overloaded version of getObjectHandler to CGHeroInstance --- lib/gameState/CGameStateCampaign.cpp | 2 +- lib/mapObjects/CGHeroInstance.cpp | 10 +++++++++- lib/mapObjects/CGHeroInstance.h | 2 ++ lib/mapObjects/CGObjectInstance.cpp | 7 +++++-- lib/mapObjects/CGObjectInstance.h | 2 +- 5 files changed, 18 insertions(+), 5 deletions(-) diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index 2178da654..c7fe97e0b 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -370,7 +370,7 @@ void CGameStateCampaign::replaceHeroesPlaceholders() heroToPlace->tempOwner = heroPlaceholder->tempOwner; heroToPlace->setAnchorPos(heroPlaceholder->anchorPos()); heroToPlace->setHeroType(heroToPlace->getHeroTypeID()); - heroToPlace->appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, heroToPlace->getHeroTypeID())->getTemplates().front(); + heroToPlace->appearance = heroToPlace->getObjectHandler()->getTemplates().front(); gameState->map->removeBlockVisTiles(heroPlaceholder, true); gameState->map->objects[heroPlaceholder->id.getNum()] = nullptr; diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index b31ff4190..f0ca7a91a 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -339,12 +339,20 @@ void CGHeroInstance::initHero(vstd::RNG & rand, const HeroTypeID & SUBID) initHero(rand); } +TObjectTypeHandler CGHeroInstance::getObjectHandler() const +{ + if (ID == Obj::HERO) + return VLC->objtypeh->getHandlerFor(ID, getHeroClass()->getIndex()); + else // prison or random hero + return VLC->objtypeh->getHandlerFor(ID, 0); +} + void CGHeroInstance::initHero(vstd::RNG & rand) { assert(validTypes(true)); if (ID == Obj::HERO) - appearance = VLC->objtypeh->getHandlerFor(Obj::HERO, getHeroClass()->getIndex())->getTemplates().front(); + appearance = getObjectHandler()->getTemplates().front(); if(!vstd::contains(spells, SpellID::PRESET)) { diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index ebb8261f8..3b971b933 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -307,6 +307,8 @@ public: std::string getHoverText(PlayerColor player) const override; std::string getMovementPointsTextIfOwner(PlayerColor player) const; + TObjectTypeHandler getObjectHandler() const override; + void afterAddToMap(CMap * map) override; void afterRemoveFromMap(CMap * map) override; diff --git a/lib/mapObjects/CGObjectInstance.cpp b/lib/mapObjects/CGObjectInstance.cpp index 5c4da7da0..7d53bfbb9 100644 --- a/lib/mapObjects/CGObjectInstance.cpp +++ b/lib/mapObjects/CGObjectInstance.cpp @@ -360,8 +360,11 @@ void CGObjectInstance::serializeJson(JsonSerializeFormat & handler) //only save here, loading is handled by map loader if(handler.saving) { - handler.serializeString("type", typeName); - handler.serializeString("subtype", subTypeName); + std::string ourTypeName = getTypeName(); + std::string ourSubtypeName = getSubtypeName(); + + handler.serializeString("type", ourTypeName); + handler.serializeString("subtype", ourSubtypeName); handler.serializeInt("x", pos.x); handler.serializeInt("y", pos.y); diff --git a/lib/mapObjects/CGObjectInstance.h b/lib/mapObjects/CGObjectInstance.h index 8df5bbba1..c201dd4db 100644 --- a/lib/mapObjects/CGObjectInstance.h +++ b/lib/mapObjects/CGObjectInstance.h @@ -101,7 +101,7 @@ public: std::optional getVisitSound(vstd::RNG & rng) const; std::optional getRemovalSound(vstd::RNG & rng) const; - TObjectTypeHandler getObjectHandler() const; + virtual TObjectTypeHandler getObjectHandler() const; /** VIRTUAL METHODS **/ From 10ad0fc760341da62295b3790d9b6c0c16326f96 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 11 Oct 2024 16:30:16 +0000 Subject: [PATCH 23/69] Split CHeroHandler.cpp/.h into 1 file per class All parts of CHeroHandler.cpp are now in lib/entities/hero Adjusted includes to use new paths No functionality changes --- AI/Nullkiller/AIGateway.cpp | 1 - AI/Nullkiller/AIUtility.cpp | 1 - AI/Nullkiller/Analyzers/HeroManager.cpp | 1 - AI/VCAI/AIUtility.cpp | 1 - AI/VCAI/MapObjectsEvaluator.cpp | 1 - AI/VCAI/VCAI.cpp | 1 - CCallback.cpp | 1 - client/CPlayerInterface.cpp | 1 - client/ClientCommandManager.cpp | 1 - client/NetPacksClient.cpp | 1 - client/adventureMap/CList.cpp | 1 - client/battle/BattleInterface.cpp | 1 - client/battle/BattleInterfaceClasses.cpp | 3 +- client/lobby/CBonusSelection.cpp | 2 +- client/lobby/CSelectionBase.cpp | 1 - client/lobby/OptionsTab.cpp | 3 +- client/mainmenu/CCampaignScreen.cpp | 1 - client/render/Graphics.cpp | 1 - client/widgets/CComponent.cpp | 9 +- client/widgets/markets/CMarketBase.cpp | 2 +- client/windows/CCreatureWindow.cpp | 2 +- client/windows/CExchangeWindow.cpp | 2 +- client/windows/CHeroOverview.cpp | 3 +- client/windows/CHeroWindow.cpp | 4 +- client/windows/CKingdomInterface.cpp | 2 +- client/windows/GUIClasses.cpp | 2 +- lib/CCreatureSet.cpp | 2 +- lib/CHeroHandler.h | 221 --------- lib/CMakeLists.txt | 11 +- lib/IGameCallback.cpp | 2 +- lib/StartInfo.cpp | 2 +- lib/VCMI_Lib.cpp | 3 +- lib/battle/BattleInfo.cpp | 1 - lib/battle/CObstacleInstance.cpp | 1 - lib/bonuses/Bonus.cpp | 12 +- lib/bonuses/Limiters.cpp | 1 - lib/constants/EntityIdentifiers.cpp | 3 +- lib/entities/faction/CTownHandler.cpp | 2 +- lib/entities/hero/CHero.cpp | 114 +++++ lib/entities/hero/CHero.h | 87 ++++ lib/entities/hero/CHeroClass.cpp | 126 +++++ lib/entities/hero/CHeroClass.h | 85 ++++ lib/entities/hero/CHeroClassHandler.cpp | 226 +++++++++ lib/entities/hero/CHeroClassHandler.h | 37 ++ lib/{ => entities/hero}/CHeroHandler.cpp | 429 +----------------- lib/entities/hero/CHeroHandler.h | 59 +++ lib/entities/hero/EHeroGender.h | 21 + lib/gameState/CGameState.cpp | 3 +- lib/gameState/CGameStateCampaign.cpp | 4 +- lib/gameState/GameStatistics.cpp | 1 - lib/gameState/InfoAboutArmy.cpp | 4 +- lib/gameState/TavernHeroesPool.cpp | 1 - lib/json/JsonRandom.cpp | 5 +- .../CommonConstructors.cpp | 2 +- lib/mapObjects/CGHeroInstance.cpp | 3 +- lib/mapObjects/CGHeroInstance.h | 2 +- lib/mapObjects/CQuest.cpp | 2 +- lib/mapping/CMap.cpp | 2 +- lib/mapping/CMapHeader.cpp | 2 +- lib/mapping/CMapInfo.cpp | 1 - lib/mapping/MapFormatH3M.cpp | 2 +- lib/mapping/MapFormatJson.cpp | 2 +- lib/mapping/MapIdentifiersH3M.cpp | 1 - lib/modding/ContentTypeHandler.cpp | 3 +- lib/networkPacks/NetPacksLib.cpp | 1 - lib/rewardable/Interface.cpp | 2 +- lib/rewardable/Limiter.cpp | 1 - lib/rmg/CMapGenerator.cpp | 3 +- lib/serializer/CSerializer.cpp | 2 +- lib/serializer/RegisterTypes.h | 1 - lib/serializer/SerializerReflection.cpp | 1 + lib/spells/BonusCaster.cpp | 2 +- lib/spells/ISpellMechanics.cpp | 1 - lib/spells/effects/Summon.cpp | 1 - lib/texts/TextLocalizationContainer.cpp | 2 +- mapeditor/graphics.cpp | 2 +- mapeditor/inspector/inspector.cpp | 3 +- mapeditor/inspector/portraitwidget.cpp | 2 +- mapeditor/inspector/questwidget.cpp | 6 +- mapeditor/inspector/rewardswidget.cpp | 6 +- mapeditor/mapcontroller.cpp | 3 +- mapeditor/maphandler.cpp | 1 - mapeditor/mapsettings/abstractsettings.cpp | 1 - mapeditor/mapsettings/mapsettings.cpp | 6 +- mapeditor/validator.cpp | 2 +- server/CGameHandler.cpp | 2 +- server/CVCMIServer.cpp | 3 +- server/processors/HeroPoolProcessor.cpp | 3 +- server/processors/PlayerMessageProcessor.cpp | 2 +- test/entity/CHeroClassTest.cpp | 2 +- test/entity/CHeroTest.cpp | 2 +- 91 files changed, 867 insertions(+), 730 deletions(-) delete mode 100644 lib/CHeroHandler.h create mode 100644 lib/entities/hero/CHero.cpp create mode 100644 lib/entities/hero/CHero.h create mode 100644 lib/entities/hero/CHeroClass.cpp create mode 100644 lib/entities/hero/CHeroClass.h create mode 100644 lib/entities/hero/CHeroClassHandler.cpp create mode 100644 lib/entities/hero/CHeroClassHandler.h rename lib/{ => entities/hero}/CHeroHandler.cpp (50%) create mode 100644 lib/entities/hero/CHeroHandler.h create mode 100644 lib/entities/hero/EHeroGender.h diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index 99172b213..a6f75d68d 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -17,7 +17,6 @@ #include "../../lib/mapObjects/ObjectTemplate.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/CConfigHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/IGameSettings.h" #include "../../lib/gameState/CGameState.h" #include "../../lib/serializer/CTypeList.h" diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index 3e89e2ba2..a5daee212 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -14,7 +14,6 @@ #include "../../lib/UnlockGuard.h" #include "../../lib/CConfigHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/mapObjects/MapObjects.h" #include "../../lib/mapping/CMapDefines.h" #include "../../lib/gameState/QuestInfo.h" diff --git a/AI/Nullkiller/Analyzers/HeroManager.cpp b/AI/Nullkiller/Analyzers/HeroManager.cpp index b6938ec1f..1f4b97c0c 100644 --- a/AI/Nullkiller/Analyzers/HeroManager.cpp +++ b/AI/Nullkiller/Analyzers/HeroManager.cpp @@ -11,7 +11,6 @@ #include "../StdInc.h" #include "../Engine/Nullkiller.h" #include "../../../lib/mapObjects/MapObjects.h" -#include "../../../lib/CHeroHandler.h" #include "../../../lib/IGameSettings.h" namespace NKAI diff --git a/AI/VCAI/AIUtility.cpp b/AI/VCAI/AIUtility.cpp index a7c4c2f7a..63a64c43b 100644 --- a/AI/VCAI/AIUtility.cpp +++ b/AI/VCAI/AIUtility.cpp @@ -15,7 +15,6 @@ #include "../../lib/UnlockGuard.h" #include "../../lib/CConfigHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CQuest.h" #include "../../lib/mapping/CMapDefines.h" diff --git a/AI/VCAI/MapObjectsEvaluator.cpp b/AI/VCAI/MapObjectsEvaluator.cpp index e430c1f08..fa038725e 100644 --- a/AI/VCAI/MapObjectsEvaluator.cpp +++ b/AI/VCAI/MapObjectsEvaluator.cpp @@ -12,7 +12,6 @@ #include "../../lib/GameConstants.h" #include "../../lib/VCMI_Lib.h" #include "../../lib/CCreatureHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/mapObjects/CompoundMapObjectID.h" #include "../../lib/mapObjectConstructors/AObjectTypeHandler.h" #include "../../lib/mapObjects/CGHeroInstance.h" diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index f9ebb1657..462023437 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -20,7 +20,6 @@ #include "../../lib/mapObjects/MapObjects.h" #include "../../lib/mapObjects/ObjectTemplate.h" #include "../../lib/CConfigHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/IGameSettings.h" #include "../../lib/gameState/CGameState.h" #include "../../lib/bonuses/Limiters.h" diff --git a/CCallback.cpp b/CCallback.cpp index 72b6e8b78..61c741cc8 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -18,7 +18,6 @@ #include "lib/mapObjects/CGHeroInstance.h" #include "lib/mapObjects/CGTownInstance.h" #include "lib/texts/CGeneralTextHandler.h" -#include "lib/CHeroHandler.h" #include "lib/CArtHandler.h" #include "lib/GameConstants.h" #include "lib/CPlayerState.h" diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 6133cdd64..abf5abb9a 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -67,7 +67,6 @@ #include "../lib/CConfigHandler.h" #include "../lib/texts/CGeneralTextHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/CPlayerState.h" #include "../lib/CRandomGenerator.h" #include "../lib/CStack.h" diff --git a/client/ClientCommandManager.cpp b/client/ClientCommandManager.cpp index 775c9b806..203ea1c68 100644 --- a/client/ClientCommandManager.cpp +++ b/client/ClientCommandManager.cpp @@ -36,7 +36,6 @@ #include "../lib/modding/CModHandler.h" #include "../lib/modding/ContentTypeHandler.h" #include "../lib/modding/ModUtility.h" -#include "../lib/CHeroHandler.h" #include "../lib/VCMIDirs.h" #include "../lib/logging/VisualLogger.h" #include "../lib/serializer/Connection.h" diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 91c8833b2..1c94e0d7d 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -32,7 +32,6 @@ #include "../lib/filesystem/FileInfo.h" #include "../lib/serializer/Connection.h" #include "../lib/texts/CGeneralTextHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/VCMI_Lib.h" #include "../lib/mapping/CMap.h" #include "../lib/VCMIDirs.h" diff --git a/client/adventureMap/CList.cpp b/client/adventureMap/CList.cpp index e730224b4..121853931 100644 --- a/client/adventureMap/CList.cpp +++ b/client/adventureMap/CList.cpp @@ -29,7 +29,6 @@ #include "../render/Colors.h" #include "../../lib/texts/CGeneralTextHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/IGameSettings.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGTownInstance.h" diff --git a/client/battle/BattleInterface.cpp b/client/battle/BattleInterface.cpp index cea4410d5..3017eff04 100644 --- a/client/battle/BattleInterface.cpp +++ b/client/battle/BattleInterface.cpp @@ -39,7 +39,6 @@ #include "../../lib/CStack.h" #include "../../lib/CConfigHandler.h" #include "../../lib/texts/CGeneralTextHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/gameState/InfoAboutArmy.h" #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/networkPacks/PacksForClientBattle.h" diff --git a/client/battle/BattleInterfaceClasses.cpp b/client/battle/BattleInterfaceClasses.cpp index 5cf6aa340..add607dad 100644 --- a/client/battle/BattleInterfaceClasses.cpp +++ b/client/battle/BattleInterfaceClasses.cpp @@ -50,10 +50,11 @@ #include "../../lib/CStack.h" #include "../../lib/CConfigHandler.h" #include "../../lib/CCreatureHandler.h" +#include "../../lib/entities/hero/CHeroClass.h" +#include "../../lib/entities/hero/CHero.h" #include "../../lib/gameState/InfoAboutArmy.h" #include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/texts/TextOperations.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/StartInfo.h" #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/networkPacks/PacksForClientBattle.h" diff --git a/client/lobby/CBonusSelection.cpp b/client/lobby/CBonusSelection.cpp index d1db2d671..32ceab982 100644 --- a/client/lobby/CBonusSelection.cpp +++ b/client/lobby/CBonusSelection.cpp @@ -41,7 +41,6 @@ #include "../../lib/CConfigHandler.h" #include "../../lib/CCreatureHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/CSkillHandler.h" #include "../../lib/StartInfo.h" #include "../../lib/entities/building/CBuilding.h" @@ -49,6 +48,7 @@ #include "../../lib/entities/faction/CFaction.h" #include "../../lib/entities/faction/CTown.h" #include "../../lib/entities/faction/CTownHandler.h" +#include "../../lib/entities/hero/CHeroHandler.h" #include "../../lib/filesystem/Filesystem.h" #include "../../lib/texts/CGeneralTextHandler.h" diff --git a/client/lobby/CSelectionBase.cpp b/client/lobby/CSelectionBase.cpp index 9a767f5f7..13d79d672 100644 --- a/client/lobby/CSelectionBase.cpp +++ b/client/lobby/CSelectionBase.cpp @@ -43,7 +43,6 @@ #include "../render/IFont.h" #include "../render/IRenderHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/CRandomGenerator.h" #include "../../lib/CThreadHelper.h" #include "../../lib/filesystem/Filesystem.h" diff --git a/client/lobby/OptionsTab.cpp b/client/lobby/OptionsTab.cpp index 002904f9f..3aa94542e 100644 --- a/client/lobby/OptionsTab.cpp +++ b/client/lobby/OptionsTab.cpp @@ -39,12 +39,13 @@ #include "../../lib/entities/faction/CFaction.h" #include "../../lib/entities/faction/CTown.h" #include "../../lib/entities/faction/CTownHandler.h" +#include "../../lib/entities/hero/CHeroHandler.h" +#include "../../lib/entities/hero/CHeroClass.h" #include "../../lib/filesystem/Filesystem.h" #include "../../lib/networkPacks/PacksForLobby.h" #include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/CArtHandler.h" #include "../../lib/CConfigHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/mapping/CMapInfo.h" #include "../../lib/mapping/CMapHeader.h" diff --git a/client/mainmenu/CCampaignScreen.cpp b/client/mainmenu/CCampaignScreen.cpp index 4644ba18d..1957ce197 100644 --- a/client/mainmenu/CCampaignScreen.cpp +++ b/client/mainmenu/CCampaignScreen.cpp @@ -37,7 +37,6 @@ #include "../../lib/spells/CSpellHandler.h" #include "../../lib/CConfigHandler.h" #include "../../lib/CSkillHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/CCreatureHandler.h" #include "../../lib/campaign/CampaignHandler.h" diff --git a/client/render/Graphics.cpp b/client/render/Graphics.cpp index 0c88f508a..9792e83e7 100644 --- a/client/render/Graphics.cpp +++ b/client/render/Graphics.cpp @@ -28,7 +28,6 @@ #include "../lib/modding/CModHandler.h" #include "../lib/modding/ModScope.h" #include "../lib/VCMI_Lib.h" -#include "../lib/CHeroHandler.h" #include diff --git a/client/widgets/CComponent.cpp b/client/widgets/CComponent.cpp index f02ba67b9..80b800492 100644 --- a/client/widgets/CComponent.cpp +++ b/client/widgets/CComponent.cpp @@ -12,9 +12,6 @@ #include "Images.h" -#include -#include - #include "../gui/CGuiHandler.h" #include "../gui/CursorHandler.h" #include "../gui/TextAlignment.h" @@ -29,7 +26,6 @@ #include "../CGameInfo.h" #include "../../lib/ArtifactUtils.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/entities/building/CBuilding.h" #include "../../lib/entities/faction/CFaction.h" #include "../../lib/entities/faction/CTown.h" @@ -42,6 +38,11 @@ #include "../../lib/CArtHandler.h" #include "../../lib/CArtifactInstance.h" +#include +#include +#include +#include + CComponent::CComponent(ComponentType Type, ComponentSubType Subtype, std::optional Val, ESize imageSize, EFonts font) { init(Type, Subtype, Val, imageSize, font, ""); diff --git a/client/widgets/markets/CMarketBase.cpp b/client/widgets/markets/CMarketBase.cpp index 02574dc67..8c6d78ec8 100644 --- a/client/widgets/markets/CMarketBase.cpp +++ b/client/widgets/markets/CMarketBase.cpp @@ -23,9 +23,9 @@ #include "../../../CCallback.h" +#include "../../../lib/entities/hero/CHeroHandler.h" #include "../../../lib/texts/CGeneralTextHandler.h" #include "../../../lib/mapObjects/CGHeroInstance.h" -#include "../../../lib/CHeroHandler.h" #include "../../../lib/mapObjects/CGMarket.h" CMarketBase::CMarketBase(const IMarket * market, const CGHeroInstance * hero) diff --git a/client/windows/CCreatureWindow.cpp b/client/windows/CCreatureWindow.cpp index 6c5612d5d..293324c3e 100644 --- a/client/windows/CCreatureWindow.cpp +++ b/client/windows/CCreatureWindow.cpp @@ -31,7 +31,7 @@ #include "../../lib/CStack.h" #include "../../lib/CBonusTypeHandler.h" #include "../../lib/IGameSettings.h" -#include "../../lib/CHeroHandler.h" +#include "../../lib/entities/hero/CHeroHandler.h" #include "../../lib/gameState/CGameState.h" #include "../../lib/networkPacks/ArtifactLocation.h" #include "../../lib/texts/CGeneralTextHandler.h" diff --git a/client/windows/CExchangeWindow.cpp b/client/windows/CExchangeWindow.cpp index 0bd8d74a3..197ef9795 100644 --- a/client/windows/CExchangeWindow.cpp +++ b/client/windows/CExchangeWindow.cpp @@ -29,8 +29,8 @@ #include "../../CCallback.h" -#include "../lib/CHeroHandler.h" #include "../lib/CSkillHandler.h" +#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/filesystem/Filesystem.h" #include "../lib/mapObjects/CGHeroInstance.h" #include "../lib/texts/CGeneralTextHandler.h" diff --git a/client/windows/CHeroOverview.cpp b/client/windows/CHeroOverview.cpp index b1719df4d..6043aefac 100644 --- a/client/windows/CHeroOverview.cpp +++ b/client/windows/CHeroOverview.cpp @@ -24,9 +24,10 @@ #include "../widgets/GraphicalPrimitiveCanvas.h" #include "../../lib/IGameSettings.h" +#include "../../lib/entities/hero/CHeroHandler.h" +#include "../../lib/entities/hero/CHeroClass.h" #include "../../lib/texts/CGeneralTextHandler.h" #include "../../lib/CCreatureHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/CSkillHandler.h" #include "../../lib/spells/CSpellHandler.h" diff --git a/client/windows/CHeroWindow.cpp b/client/windows/CHeroWindow.cpp index 809f937f0..9599fb567 100644 --- a/client/windows/CHeroWindow.cpp +++ b/client/windows/CHeroWindow.cpp @@ -35,11 +35,11 @@ #include "../lib/ArtifactUtils.h" #include "../lib/CArtHandler.h" #include "../lib/CConfigHandler.h" +#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/texts/CGeneralTextHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/CSkillHandler.h" #include "../lib/mapObjects/CGHeroInstance.h" -#include "../../lib/networkPacks/ArtifactLocation.h" +#include "../lib/networkPacks/ArtifactLocation.h" void CHeroSwitcher::clickPressed(const Point & cursorPosition) { diff --git a/client/windows/CKingdomInterface.cpp b/client/windows/CKingdomInterface.cpp index 6c99bbca6..0d754741f 100644 --- a/client/windows/CKingdomInterface.cpp +++ b/client/windows/CKingdomInterface.cpp @@ -33,8 +33,8 @@ #include "../../lib/CConfigHandler.h" #include "../../lib/CCreatureHandler.h" +#include "../../lib/entities/hero/CHeroHandler.h" #include "../../lib/texts/CGeneralTextHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/IGameSettings.h" #include "../../lib/CSkillHandler.h" #include "../../lib/StartInfo.h" diff --git a/client/windows/GUIClasses.cpp b/client/windows/GUIClasses.cpp index 46406d4d4..32d485a1f 100644 --- a/client/windows/GUIClasses.cpp +++ b/client/windows/GUIClasses.cpp @@ -44,6 +44,7 @@ #include "../lib/entities/building/CBuilding.h" #include "../lib/entities/faction/CTownHandler.h" +#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/mapObjectConstructors/CObjectClassesHandler.h" #include "../lib/mapObjectConstructors/CommonConstructors.h" #include "../lib/mapObjects/CGHeroInstance.h" @@ -53,7 +54,6 @@ #include "../lib/gameState/SThievesGuildInfo.h" #include "../lib/gameState/TavernHeroesPool.h" #include "../lib/texts/CGeneralTextHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/IGameSettings.h" #include "ConditionalWait.h" #include "../lib/CRandomGenerator.h" diff --git a/lib/CCreatureSet.cpp b/lib/CCreatureSet.cpp index 5de5a3420..3a9d971dc 100644 --- a/lib/CCreatureSet.cpp +++ b/lib/CCreatureSet.cpp @@ -15,12 +15,12 @@ #include "CCreatureHandler.h" #include "VCMI_Lib.h" #include "IGameSettings.h" +#include "entities/hero/CHeroHandler.h" #include "mapObjects/CGHeroInstance.h" #include "modding/ModScope.h" #include "IGameCallback.h" #include "texts/CGeneralTextHandler.h" #include "spells/CSpellHandler.h" -#include "CHeroHandler.h" #include "IBonusTypeHandler.h" #include "serializer/JsonSerializeFormat.h" diff --git a/lib/CHeroHandler.h b/lib/CHeroHandler.h deleted file mode 100644 index c2bd9d220..000000000 --- a/lib/CHeroHandler.h +++ /dev/null @@ -1,221 +0,0 @@ -/* - * CHeroHandler.h, part of VCMI engine - * - * Authors: listed in file AUTHORS in main folder - * - * License: GNU General Public License v2.0 or later - * Full text of license available in license.txt file, in main folder - * - */ -#pragma once - -#include -#include -#include -#include - -#include "ConstTransitivePtr.h" -#include "GameConstants.h" -#include "bonuses/Bonus.h" -#include "bonuses/BonusList.h" -#include "IHandlerBase.h" -#include "filesystem/ResourcePath.h" - -VCMI_LIB_NAMESPACE_BEGIN - -namespace vstd -{ -class RNG; -} - -class CHeroClass; -class CGHeroInstance; -struct BattleHex; -class JsonNode; -class JsonSerializeFormat; -class BattleField; - -enum class EHeroGender : int8_t -{ - DEFAULT = -1, // from h3m, instance has same gender as hero type - MALE = 0, - FEMALE = 1, -}; - -class DLL_LINKAGE CHero : public HeroType -{ - friend class CHeroHandler; - - HeroTypeID ID; - std::string identifier; - std::string modScope; - -public: - struct InitialArmyStack - { - ui32 minAmount; - ui32 maxAmount; - CreatureID creature; - }; - si32 imageIndex = 0; - - std::vector initialArmy; - - const CHeroClass * heroClass = nullptr; - std::vector > secSkillsInit; //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert) - BonusList specialty; - std::set spells; - bool haveSpellBook = false; - bool special = false; // hero is special and won't be placed in game (unless preset on map), e.g. campaign heroes - bool onlyOnWaterMap; // hero will be placed only if the map contains water - bool onlyOnMapWithoutWater; // hero will be placed only if the map does not contain water - EHeroGender gender = EHeroGender::MALE; // default sex: 0=male, 1=female - - /// Graphics - std::string iconSpecSmall; - std::string iconSpecLarge; - std::string portraitSmall; - std::string portraitLarge; - AnimationPath battleImage; - - CHero(); - virtual ~CHero(); - - int32_t getIndex() const override; - int32_t getIconIndex() const override; - std::string getJsonKey() const override; - std::string getModScope() const override; - HeroTypeID getId() const override; - void registerIcons(const IconRegistar & cb) const override; - - std::string getNameTranslated() const override; - std::string getBiographyTranslated() const override; - std::string getSpecialtyNameTranslated() const override; - std::string getSpecialtyDescriptionTranslated() const override; - std::string getSpecialtyTooltipTranslated() const override; - - std::string getNameTextID() const override; - std::string getBiographyTextID() const override; - std::string getSpecialtyNameTextID() const override; - std::string getSpecialtyDescriptionTextID() const override; - std::string getSpecialtyTooltipTextID() const override; - - void updateFrom(const JsonNode & data); - void serializeJson(JsonSerializeFormat & handler); -}; - -class DLL_LINKAGE CHeroClass : public HeroClass -{ - friend class CHeroClassHandler; - HeroClassID id; // use getId instead - std::string modScope; - std::string identifier; // use getJsonKey instead - -public: - enum EClassAffinity - { - MIGHT, - MAGIC - }; - - //double aggression; // not used in vcmi. - FactionID faction; - ui8 affinity; // affinity, using EClassAffinity enum - - // default chance for hero of specific class to appear in tavern, if field "tavern" was not set - // resulting chance = sqrt(town.chance * heroClass.chance) - ui32 defaultTavernChance; - - CreatureID commander; - - std::vector primarySkillInitial; // initial primary skills - std::vector primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level - std::vector primarySkillHighLevel;// same for high levels (> 10) - - std::map secSkillProbability; //probabilities of gaining secondary skills (out of 112), in id order - - std::map selectionProbability; //probability of selection in towns - - AnimationPath imageBattleMale; - AnimationPath imageBattleFemale; - std::string imageMapMale; - std::string imageMapFemale; - - CHeroClass(); - - int32_t getIndex() const override; - int32_t getIconIndex() const override; - std::string getJsonKey() const override; - std::string getModScope() const override; - HeroClassID getId() const override; - void registerIcons(const IconRegistar & cb) const override; - - std::string getNameTranslated() const override; - std::string getNameTextID() const override; - - bool isMagicHero() const; - SecondarySkill chooseSecSkill(const std::set & possibles, vstd::RNG & rand) const; //picks secondary skill out from given possibilities - - void updateFrom(const JsonNode & data); - void serializeJson(JsonSerializeFormat & handler); - - EAlignment getAlignment() const; - - int tavernProbability(FactionID faction) const; -}; - -class DLL_LINKAGE CHeroClassHandler : public CHandlerBase -{ - void fillPrimarySkillData(const JsonNode & node, CHeroClass * heroClass, PrimarySkill pSkill) const; - -public: - std::vector loadLegacyData() override; - - void afterLoadFinalization() override; - - ~CHeroClassHandler(); - -protected: - const std::vector & getTypeNames() const override; - std::shared_ptr loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) override; - -}; - -class DLL_LINKAGE CHeroHandler : public CHandlerBase -{ - /// expPerLEvel[i] is amount of exp needed to reach level i; - /// consists of 196 values. Any higher levels require experience larger that TExpType can hold - std::vector expPerLevel; - - /// helpers for loading to avoid huge load functions - void loadHeroArmy(CHero * hero, const JsonNode & node) const; - void loadHeroSkills(CHero * hero, const JsonNode & node) const; - void loadHeroSpecialty(CHero * hero, const JsonNode & node); - - void loadExperience(); - - std::vector> callAfterLoadFinalization; - -public: - ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount - TExpType reqExp(ui32 level) const; //calculates experience required for given level - ui32 maxSupportedLevel() const; - - std::vector loadLegacyData() override; - - void beforeValidate(JsonNode & object) override; - void loadObject(std::string scope, std::string name, const JsonNode & data) override; - void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override; - void afterLoadFinalization() override; - - CHeroHandler(); - ~CHeroHandler(); - - std::set getDefaultAllowed() const; - -protected: - const std::vector & getTypeNames() const override; - std::shared_ptr loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) override; -}; - -VCMI_LIB_NAMESPACE_END diff --git a/lib/CMakeLists.txt b/lib/CMakeLists.txt index 37cb28106..0db2f9e50 100644 --- a/lib/CMakeLists.txt +++ b/lib/CMakeLists.txt @@ -87,6 +87,10 @@ set(lib_MAIN_SRCS entities/faction/CFaction.cpp entities/faction/CTown.cpp entities/faction/CTownHandler.cpp + entities/hero/CHero.cpp + entities/hero/CHeroClass.cpp + entities/hero/CHeroClassHandler.cpp + entities/hero/CHeroHandler.cpp events/ApplyDamage.cpp events/GameResumed.cpp @@ -270,7 +274,6 @@ set(lib_MAIN_SRCS CCreatureSet.cpp CGameInfoCallback.cpp CGameInterface.cpp - CHeroHandler.cpp CPlayerState.cpp CRandomGenerator.cpp CScriptingModule.cpp @@ -458,6 +461,11 @@ set(lib_MAIN_HEADERS entities/faction/CFaction.h entities/faction/CTown.h entities/faction/CTownHandler.h + entities/hero/CHero.h + entities/hero/CHeroClass.h + entities/hero/CHeroClassHandler.h + entities/hero/CHeroHandler.h + entities/hero/EHeroGender.h events/ApplyDamage.h events/GameResumed.h @@ -683,7 +691,6 @@ set(lib_MAIN_HEADERS CCreatureSet.h CGameInfoCallback.h CGameInterface.h - CHeroHandler.h ConstTransitivePtr.h Color.h CPlayerState.h diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index fa73d0101..cb32dcb50 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -10,7 +10,6 @@ #include "StdInc.h" #include "IGameCallback.h" -#include "CHeroHandler.h" // for CHeroHandler #include "spells/CSpellHandler.h"// for CSpell #include "CSkillHandler.h"// for CSkill #include "CBonusTypeHandler.h" @@ -20,6 +19,7 @@ #include "bonuses/Propagators.h" #include "bonuses/Updaters.h" #include "entities/building/CBuilding.h" +#include "entities/hero/CHero.h" #include "networkPacks/ArtifactLocation.h" #include "serializer/CLoadFile.h" #include "serializer/CSaveFile.h" diff --git a/lib/StartInfo.cpp b/lib/StartInfo.cpp index b1abfe7b6..f6ca7d6cc 100644 --- a/lib/StartInfo.cpp +++ b/lib/StartInfo.cpp @@ -11,10 +11,10 @@ #include "StartInfo.h" #include "texts/CGeneralTextHandler.h" -#include "CHeroHandler.h" #include "VCMI_Lib.h" #include "entities/faction/CFaction.h" #include "entities/faction/CTownHandler.h" +#include "entities/hero/CHeroHandler.h" #include "rmg/CMapGenOptions.h" #include "mapping/CMapInfo.h" #include "campaign/CampaignState.h" diff --git a/lib/VCMI_Lib.cpp b/lib/VCMI_Lib.cpp index c516947bd..91d3da34b 100644 --- a/lib/VCMI_Lib.cpp +++ b/lib/VCMI_Lib.cpp @@ -14,7 +14,6 @@ #include "CArtHandler.h" #include "CBonusTypeHandler.h" #include "CCreatureHandler.h" -#include "CHeroHandler.h" #include "CConfigHandler.h" #include "RoadHandler.h" #include "RiverHandler.h" @@ -23,6 +22,8 @@ #include "spells/effects/Registry.h" #include "CSkillHandler.h" #include "entities/faction/CTownHandler.h" +#include "entities/hero/CHeroClassHandler.h" +#include "entities/hero/CHeroHandler.h" #include "texts/CGeneralTextHandler.h" #include "modding/CModHandler.h" #include "modding/CModInfo.h" diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index 5bbebc49c..8a8eb633c 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -15,7 +15,6 @@ #include "bonuses/Limiters.h" #include "bonuses/Updaters.h" #include "../CStack.h" -#include "../CHeroHandler.h" #include "../entities/building/TownFortifications.h" #include "../filesystem/Filesystem.h" #include "../mapObjects/CGTownInstance.h" diff --git a/lib/battle/CObstacleInstance.cpp b/lib/battle/CObstacleInstance.cpp index 098d980a2..6bb5c65f3 100644 --- a/lib/battle/CObstacleInstance.cpp +++ b/lib/battle/CObstacleInstance.cpp @@ -9,7 +9,6 @@ */ #include "StdInc.h" #include "CObstacleInstance.h" -#include "../CHeroHandler.h" #include "../ObstacleHandler.h" #include "../VCMI_Lib.h" diff --git a/lib/bonuses/Bonus.cpp b/lib/bonuses/Bonus.cpp index 2f1cb519b..a11e794f4 100644 --- a/lib/bonuses/Bonus.cpp +++ b/lib/bonuses/Bonus.cpp @@ -14,18 +14,18 @@ #include "Updaters.h" #include "Propagators.h" -#include "../VCMI_Lib.h" -#include "../spells/CSpellHandler.h" +#include "../CArtHandler.h" #include "../CCreatureHandler.h" #include "../CCreatureSet.h" -#include "../CHeroHandler.h" -#include "../texts/CGeneralTextHandler.h" #include "../CSkillHandler.h" -#include "../CArtHandler.h" #include "../TerrainHandler.h" -#include "../constants/StringConstants.h" +#include "../VCMI_Lib.h" #include "../battle/BattleInfo.h" +#include "../constants/StringConstants.h" +#include "../entities/hero/CHero.h" #include "../modding/ModUtility.h" +#include "../spells/CSpellHandler.h" +#include "../texts/CGeneralTextHandler.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/bonuses/Limiters.cpp b/lib/bonuses/Limiters.cpp index 914081139..0fa15f9d4 100644 --- a/lib/bonuses/Limiters.cpp +++ b/lib/bonuses/Limiters.cpp @@ -17,7 +17,6 @@ #include "../spells/CSpellHandler.h" #include "../CCreatureHandler.h" #include "../CCreatureSet.h" -#include "../CHeroHandler.h" #include "../texts/CGeneralTextHandler.h" #include "../CSkillHandler.h" #include "../CStack.h" diff --git a/lib/constants/EntityIdentifiers.cpp b/lib/constants/EntityIdentifiers.cpp index 599920523..2c3f183c5 100644 --- a/lib/constants/EntityIdentifiers.cpp +++ b/lib/constants/EntityIdentifiers.cpp @@ -29,12 +29,13 @@ #include "modding/IdentifierStorage.h" #include "modding/ModScope.h" #include "VCMI_Lib.h" -#include "CHeroHandler.h" #include "CArtHandler.h"//todo: remove #include "CCreatureHandler.h"//todo: remove #include "spells/CSpellHandler.h" //todo: remove #include "CSkillHandler.h"//todo: remove #include "entities/faction/CFaction.h" +#include "entities/hero/CHero.h" +#include "entities/hero/CHeroClass.h" #include "mapObjectConstructors/AObjectTypeHandler.h" #include "constants/StringConstants.h" #include "texts/CGeneralTextHandler.h" diff --git a/lib/entities/faction/CTownHandler.cpp b/lib/entities/faction/CTownHandler.cpp index 09a99ed71..91d05852b 100644 --- a/lib/entities/faction/CTownHandler.cpp +++ b/lib/entities/faction/CTownHandler.cpp @@ -13,9 +13,9 @@ #include "CTown.h" #include "CFaction.h" #include "../building/CBuilding.h" +#include "../hero/CHeroClassHandler.h" #include "../../CCreatureHandler.h" -#include "../../CHeroHandler.h" #include "../../IGameSettings.h" #include "../../TerrainHandler.h" #include "../../VCMI_Lib.h" diff --git a/lib/entities/hero/CHero.cpp b/lib/entities/hero/CHero.cpp new file mode 100644 index 000000000..4b9b363f1 --- /dev/null +++ b/lib/entities/hero/CHero.cpp @@ -0,0 +1,114 @@ +/* + * CHero.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "CHero.h" + +#include "../../VCMI_Lib.h" +#include "../../texts/CGeneralTextHandler.h" + +VCMI_LIB_NAMESPACE_BEGIN + +CHero::CHero() = default; +CHero::~CHero() = default; + +int32_t CHero::getIndex() const +{ + return ID.getNum(); +} + +int32_t CHero::getIconIndex() const +{ + return imageIndex; +} + +std::string CHero::getJsonKey() const +{ + return modScope + ':' + identifier; +} + +std::string CHero::getModScope() const +{ + return modScope; +} + +HeroTypeID CHero::getId() const +{ + return ID; +} + +std::string CHero::getNameTranslated() const +{ + return VLC->generaltexth->translate(getNameTextID()); +} + +std::string CHero::getBiographyTranslated() const +{ + return VLC->generaltexth->translate(getBiographyTextID()); +} + +std::string CHero::getSpecialtyNameTranslated() const +{ + return VLC->generaltexth->translate(getSpecialtyNameTextID()); +} + +std::string CHero::getSpecialtyDescriptionTranslated() const +{ + return VLC->generaltexth->translate(getSpecialtyDescriptionTextID()); +} + +std::string CHero::getSpecialtyTooltipTranslated() const +{ + return VLC->generaltexth->translate(getSpecialtyTooltipTextID()); +} + +std::string CHero::getNameTextID() const +{ + return TextIdentifier("hero", modScope, identifier, "name").get(); +} + +std::string CHero::getBiographyTextID() const +{ + return TextIdentifier("hero", modScope, identifier, "biography").get(); +} + +std::string CHero::getSpecialtyNameTextID() const +{ + return TextIdentifier("hero", modScope, identifier, "specialty", "name").get(); +} + +std::string CHero::getSpecialtyDescriptionTextID() const +{ + return TextIdentifier("hero", modScope, identifier, "specialty", "description").get(); +} + +std::string CHero::getSpecialtyTooltipTextID() const +{ + return TextIdentifier("hero", modScope, identifier, "specialty", "tooltip").get(); +} + +void CHero::registerIcons(const IconRegistar & cb) const +{ + cb(getIconIndex(), 0, "UN32", iconSpecSmall); + cb(getIconIndex(), 0, "UN44", iconSpecLarge); + cb(getIconIndex(), 0, "PORTRAITSLARGE", portraitLarge); + cb(getIconIndex(), 0, "PORTRAITSSMALL", portraitSmall); +} + +void CHero::updateFrom(const JsonNode & data) +{ + //todo: CHero::updateFrom +} + +void CHero::serializeJson(JsonSerializeFormat & handler) +{ + +} + +VCMI_LIB_NAMESPACE_END diff --git a/lib/entities/hero/CHero.h b/lib/entities/hero/CHero.h new file mode 100644 index 000000000..1b96cc341 --- /dev/null +++ b/lib/entities/hero/CHero.h @@ -0,0 +1,87 @@ +/* + * CHero.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include + +#include "EHeroGender.h" + +#include "../../bonuses/BonusList.h" +#include "../../constants/EntityIdentifiers.h" +#include "../../filesystem/ResourcePath.h" + +VCMI_LIB_NAMESPACE_BEGIN + +class DLL_LINKAGE CHero : public HeroType +{ + friend class CHeroHandler; + + HeroTypeID ID; + std::string identifier; + std::string modScope; + +public: + struct InitialArmyStack + { + ui32 minAmount; + ui32 maxAmount; + CreatureID creature; + }; + si32 imageIndex = 0; + + std::vector initialArmy; + + const CHeroClass * heroClass = nullptr; + + //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert) + std::vector> secSkillsInit; + + BonusList specialty; + std::set spells; + bool haveSpellBook = false; + bool special = false; // hero is special and won't be placed in game (unless preset on map), e.g. campaign heroes + bool onlyOnWaterMap; // hero will be placed only if the map contains water + bool onlyOnMapWithoutWater; // hero will be placed only if the map does not contain water + EHeroGender gender = EHeroGender::MALE; // default sex: 0=male, 1=female + + /// Graphics + std::string iconSpecSmall; + std::string iconSpecLarge; + std::string portraitSmall; + std::string portraitLarge; + AnimationPath battleImage; + + CHero(); + virtual ~CHero(); + + int32_t getIndex() const override; + int32_t getIconIndex() const override; + std::string getJsonKey() const override; + std::string getModScope() const override; + HeroTypeID getId() const override; + void registerIcons(const IconRegistar & cb) const override; + + std::string getNameTranslated() const override; + std::string getBiographyTranslated() const override; + std::string getSpecialtyNameTranslated() const override; + std::string getSpecialtyDescriptionTranslated() const override; + std::string getSpecialtyTooltipTranslated() const override; + + std::string getNameTextID() const override; + std::string getBiographyTextID() const override; + std::string getSpecialtyNameTextID() const override; + std::string getSpecialtyDescriptionTextID() const override; + std::string getSpecialtyTooltipTextID() const override; + + void updateFrom(const JsonNode & data); + void serializeJson(JsonSerializeFormat & handler); +}; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/entities/hero/CHeroClass.cpp b/lib/entities/hero/CHeroClass.cpp new file mode 100644 index 000000000..da6355e70 --- /dev/null +++ b/lib/entities/hero/CHeroClass.cpp @@ -0,0 +1,126 @@ +/* + * CHeroClass.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "CHeroClass.h" + +#include "../faction/CFaction.h" + +#include "../../VCMI_Lib.h" +#include "../../texts/CGeneralTextHandler.h" + +#include + +VCMI_LIB_NAMESPACE_BEGIN + +SecondarySkill CHeroClass::chooseSecSkill(const std::set & possibles, vstd::RNG & rand) const //picks secondary skill out from given possibilities +{ + assert(!possibles.empty()); + + if (possibles.size() == 1) + return *possibles.begin(); + + int totalProb = 0; + for(const auto & possible : possibles) + if (secSkillProbability.count(possible) != 0) + totalProb += secSkillProbability.at(possible); + + if (totalProb == 0) // may trigger if set contains only banned skills (0 probability) + return *RandomGeneratorUtil::nextItem(possibles, rand); + + auto ran = rand.nextInt(totalProb - 1); + for(const auto & possible : possibles) + { + if (secSkillProbability.count(possible) != 0) + ran -= secSkillProbability.at(possible); + + if(ran < 0) + return possible; + } + + assert(0); // should not be possible + return *possibles.begin(); +} + +bool CHeroClass::isMagicHero() const +{ + return affinity == MAGIC; +} + +int CHeroClass::tavernProbability(FactionID targetFaction) const +{ + auto it = selectionProbability.find(targetFaction); + if (it != selectionProbability.end()) + return it->second; + return 0; +} + +EAlignment CHeroClass::getAlignment() const +{ + return faction.toEntity(VLC)->getAlignment(); +} + +int32_t CHeroClass::getIndex() const +{ + return id.getNum(); +} + +int32_t CHeroClass::getIconIndex() const +{ + return getIndex(); +} + +std::string CHeroClass::getJsonKey() const +{ + return modScope + ':' + identifier; +} + +std::string CHeroClass::getModScope() const +{ + return modScope; +} + +HeroClassID CHeroClass::getId() const +{ + return id; +} + +void CHeroClass::registerIcons(const IconRegistar & cb) const +{ + +} + +std::string CHeroClass::getNameTranslated() const +{ + return VLC->generaltexth->translate(getNameTextID()); +} + +std::string CHeroClass::getNameTextID() const +{ + return TextIdentifier("heroClass", modScope, identifier, "name").get(); +} + +void CHeroClass::updateFrom(const JsonNode & data) +{ + //TODO: CHeroClass::updateFrom +} + +void CHeroClass::serializeJson(JsonSerializeFormat & handler) +{ + +} + +CHeroClass::CHeroClass(): + faction(0), + affinity(0), + defaultTavernChance(0) +{ +} + +VCMI_LIB_NAMESPACE_END diff --git a/lib/entities/hero/CHeroClass.h b/lib/entities/hero/CHeroClass.h new file mode 100644 index 000000000..0d4edc5a6 --- /dev/null +++ b/lib/entities/hero/CHeroClass.h @@ -0,0 +1,85 @@ +/* + * CHeroClass.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include + +#include "../../constants/EntityIdentifiers.h" +#include "../../constants/Enumerations.h" +#include "../../filesystem/ResourcePath.h" + +VCMI_LIB_NAMESPACE_BEGIN + +namespace vstd +{ +class RNG; +} + +class DLL_LINKAGE CHeroClass : public HeroClass +{ + friend class CHeroClassHandler; + HeroClassID id; // use getId instead + std::string modScope; + std::string identifier; // use getJsonKey instead + +public: + enum EClassAffinity + { + MIGHT, + MAGIC + }; + + //double aggression; // not used in vcmi. + FactionID faction; + ui8 affinity; // affinity, using EClassAffinity enum + + // default chance for hero of specific class to appear in tavern, if field "tavern" was not set + // resulting chance = sqrt(town.chance * heroClass.chance) + ui32 defaultTavernChance; + + CreatureID commander; + + std::vector primarySkillInitial; // initial primary skills + std::vector primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level + std::vector primarySkillHighLevel; // same for high levels (> 10) + + std::map secSkillProbability; //probabilities of gaining secondary skills (out of 112), in id order + + std::map selectionProbability; //probability of selection in towns + + AnimationPath imageBattleMale; + AnimationPath imageBattleFemale; + std::string imageMapMale; + std::string imageMapFemale; + + CHeroClass(); + + int32_t getIndex() const override; + int32_t getIconIndex() const override; + std::string getJsonKey() const override; + std::string getModScope() const override; + HeroClassID getId() const override; + void registerIcons(const IconRegistar & cb) const override; + + std::string getNameTranslated() const override; + std::string getNameTextID() const override; + + bool isMagicHero() const; + SecondarySkill chooseSecSkill(const std::set & possibles, vstd::RNG & rand) const; //picks secondary skill out from given possibilities + + void updateFrom(const JsonNode & data); + void serializeJson(JsonSerializeFormat & handler); + + EAlignment getAlignment() const; + + int tavernProbability(FactionID faction) const; +}; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/entities/hero/CHeroClassHandler.cpp b/lib/entities/hero/CHeroClassHandler.cpp new file mode 100644 index 000000000..e9207a229 --- /dev/null +++ b/lib/entities/hero/CHeroClassHandler.cpp @@ -0,0 +1,226 @@ +/* + * CHeroClassHandler.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#include "StdInc.h" +#include "CHeroClassHandler.h" + +#include "CHeroClass.h" + +#include "../faction/CTown.h" +#include "../faction/CTownHandler.h" + +#include "../../CSkillHandler.h" +#include "../../IGameSettings.h" +#include "../../VCMI_Lib.h" +#include "../../constants/StringConstants.h" +#include "../../json/JsonNode.h" +#include "../../mapObjectConstructors/AObjectTypeHandler.h" +#include "../../mapObjectConstructors/CObjectClassesHandler.h" +#include "../../modding/IdentifierStorage.h" +#include "../../texts/CGeneralTextHandler.h" +#include "../../texts/CLegacyConfigParser.h" + +VCMI_LIB_NAMESPACE_BEGIN + +void CHeroClassHandler::fillPrimarySkillData(const JsonNode & node, CHeroClass * heroClass, PrimarySkill pSkill) const +{ + const auto & skillName = NPrimarySkill::names[pSkill.getNum()]; + auto currentPrimarySkillValue = static_cast(node["primarySkills"][skillName].Integer()); + int primarySkillLegalMinimum = VLC->engineSettings()->getVector(EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS)[pSkill.getNum()]; + + if(currentPrimarySkillValue < primarySkillLegalMinimum) + { + logMod->error("Hero class '%s' has incorrect initial value '%d' for skill '%s'. Value '%d' will be used instead.", + heroClass->getNameTranslated(), currentPrimarySkillValue, skillName, primarySkillLegalMinimum); + currentPrimarySkillValue = primarySkillLegalMinimum; + } + heroClass->primarySkillInitial.push_back(currentPrimarySkillValue); + heroClass->primarySkillLowLevel.push_back(static_cast(node["lowLevelChance"][skillName].Float())); + heroClass->primarySkillHighLevel.push_back(static_cast(node["highLevelChance"][skillName].Float())); +} + +const std::vector & CHeroClassHandler::getTypeNames() const +{ + static const std::vector typeNames = { "heroClass" }; + return typeNames; +} + +std::shared_ptr CHeroClassHandler::loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) +{ + assert(identifier.find(':') == std::string::npos); + assert(!scope.empty()); + + std::string affinityStr[2] = { "might", "magic" }; + + auto heroClass = std::make_shared(); + + heroClass->id = HeroClassID(index); + heroClass->identifier = identifier; + heroClass->modScope = scope; + heroClass->imageBattleFemale = AnimationPath::fromJson(node["animation"]["battle"]["female"]); + heroClass->imageBattleMale = AnimationPath::fromJson(node["animation"]["battle"]["male"]); + //MODS COMPATIBILITY FOR 0.96 + heroClass->imageMapFemale = node["animation"]["map"]["female"].String(); + heroClass->imageMapMale = node["animation"]["map"]["male"].String(); + + VLC->generaltexth->registerString(scope, heroClass->getNameTextID(), node["name"].String()); + + if (vstd::contains(affinityStr, node["affinity"].String())) + { + heroClass->affinity = vstd::find_pos(affinityStr, node["affinity"].String()); + } + else + { + logGlobal->error("Mod '%s', hero class '%s': invalid affinity '%s'! Expected 'might' or 'magic'!", scope, identifier, node["affinity"].String()); + heroClass->affinity = CHeroClass::MIGHT; + } + + fillPrimarySkillData(node, heroClass.get(), PrimarySkill::ATTACK); + fillPrimarySkillData(node, heroClass.get(), PrimarySkill::DEFENSE); + fillPrimarySkillData(node, heroClass.get(), PrimarySkill::SPELL_POWER); + fillPrimarySkillData(node, heroClass.get(), PrimarySkill::KNOWLEDGE); + + auto percentSumm = std::accumulate(heroClass->primarySkillLowLevel.begin(), heroClass->primarySkillLowLevel.end(), 0); + if(percentSumm <= 0) + logMod->error("Hero class %s has wrong lowLevelChance values: must be above zero!", heroClass->identifier, percentSumm); + + percentSumm = std::accumulate(heroClass->primarySkillHighLevel.begin(), heroClass->primarySkillHighLevel.end(), 0); + if(percentSumm <= 0) + logMod->error("Hero class %s has wrong highLevelChance values: must be above zero!", heroClass->identifier, percentSumm); + + for(auto skillPair : node["secondarySkills"].Struct()) + { + int probability = static_cast(skillPair.second.Integer()); + VLC->identifiers()->requestIdentifier(skillPair.second.getModScope(), "skill", skillPair.first, [heroClass, probability](si32 skillID) + { + heroClass->secSkillProbability[skillID] = probability; + }); + } + + VLC->identifiers()->requestIdentifier ("creature", node["commander"], + [=](si32 commanderID) + { + heroClass->commander = CreatureID(commanderID); + }); + + heroClass->defaultTavernChance = static_cast(node["defaultTavern"].Float()); + for(const auto & tavern : node["tavern"].Struct()) + { + int value = static_cast(tavern.second.Float()); + + VLC->identifiers()->requestIdentifier(tavern.second.getModScope(), "faction", tavern.first, + [=](si32 factionID) + { + heroClass->selectionProbability[FactionID(factionID)] = value; + }); + } + + VLC->identifiers()->requestIdentifier("faction", node["faction"], + [=](si32 factionID) + { + heroClass->faction.setNum(factionID); + }); + + VLC->identifiers()->requestIdentifier(scope, "object", "hero", [=](si32 index) + { + JsonNode classConf = node["mapObject"]; + classConf["heroClass"].String() = identifier; + if (!node["compatibilityIdentifiers"].isNull()) + classConf["compatibilityIdentifiers"] = node["compatibilityIdentifiers"]; + classConf.setModScope(scope); + VLC->objtypeh->loadSubObject(identifier, classConf, index, heroClass->getIndex()); + }); + + return heroClass; +} + +std::vector CHeroClassHandler::loadLegacyData() +{ + size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_HERO_CLASS); + + objects.resize(dataSize); + std::vector h3Data; + h3Data.reserve(dataSize); + + CLegacyConfigParser parser(TextPath::builtin("DATA/HCTRAITS.TXT")); + + parser.endLine(); // header + parser.endLine(); + + for (size_t i=0; i set selection probability if it was not set before in tavern entries + for(auto & heroClass : objects) + { + for(auto & faction : VLC->townh->objects) + { + if (!faction->town) + continue; + if (heroClass->selectionProbability.count(faction->getId())) + continue; + + auto chance = static_cast(heroClass->defaultTavernChance * faction->town->defaultTavernChance); + heroClass->selectionProbability[faction->getId()] = static_cast(sqrt(chance) + 0.5); //FIXME: replace with std::round once MVS supports it + } + + // set default probabilities for gaining secondary skills where not loaded previously + for(int skillID = 0; skillID < VLC->skillh->size(); skillID++) + { + if(heroClass->secSkillProbability.count(skillID) == 0) + { + const CSkill * skill = (*VLC->skillh)[SecondarySkill(skillID)]; + logMod->trace("%s: no probability for %s, using default", heroClass->identifier, skill->getJsonKey()); + heroClass->secSkillProbability[skillID] = skill->gainChance[heroClass->affinity]; + } + } + } + + for(const auto & hc : objects) + { + if(!hc->imageMapMale.empty()) + { + JsonNode templ; + templ["animation"].String() = hc->imageMapMale; + VLC->objtypeh->getHandlerFor(Obj::HERO, hc->getIndex())->addTemplate(templ); + } + } +} + +CHeroClassHandler::~CHeroClassHandler() = default; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/entities/hero/CHeroClassHandler.h b/lib/entities/hero/CHeroClassHandler.h new file mode 100644 index 000000000..e04a6dbf3 --- /dev/null +++ b/lib/entities/hero/CHeroClassHandler.h @@ -0,0 +1,37 @@ +/* + * CHeroClassHandler.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include + +#include "CHeroClass.h" // convenience include - users of handler generally also use its entity + +#include "../../IHandlerBase.h" +#include "../../constants/EntityIdentifiers.h" + +VCMI_LIB_NAMESPACE_BEGIN + +class DLL_LINKAGE CHeroClassHandler : public CHandlerBase +{ + void fillPrimarySkillData(const JsonNode & node, CHeroClass * heroClass, PrimarySkill pSkill) const; + +public: + std::vector loadLegacyData() override; + + void afterLoadFinalization() override; + + ~CHeroClassHandler(); + +protected: + const std::vector & getTypeNames() const override; + std::shared_ptr loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) override; +}; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/CHeroHandler.cpp b/lib/entities/hero/CHeroHandler.cpp similarity index 50% rename from lib/CHeroHandler.cpp rename to lib/entities/hero/CHeroHandler.cpp index 820f8404d..8b05df0eb 100644 --- a/lib/CHeroHandler.cpp +++ b/lib/entities/hero/CHeroHandler.cpp @@ -10,427 +10,22 @@ #include "StdInc.h" #include "CHeroHandler.h" -#include "filesystem/Filesystem.h" -#include "VCMI_Lib.h" -#include "constants/StringConstants.h" -#include "battle/BattleHex.h" -#include "CCreatureHandler.h" -#include "IGameSettings.h" -#include "CSkillHandler.h" -#include "BattleFieldHandler.h" -#include "bonuses/Limiters.h" -#include "bonuses/Updaters.h" -#include "entities/faction/CFaction.h" -#include "entities/faction/CTown.h" -#include "entities/faction/CTownHandler.h" -#include "json/JsonBonus.h" -#include "json/JsonUtils.h" -#include "mapObjectConstructors/AObjectTypeHandler.h" -#include "mapObjectConstructors/CObjectClassesHandler.h" -#include "modding/IdentifierStorage.h" -#include "texts/CGeneralTextHandler.h" -#include "texts/CLegacyConfigParser.h" +#include "CHero.h" -#include +#include "../../VCMI_Lib.h" +#include "../../constants/StringConstants.h" +#include "../../CCreatureHandler.h" +#include "../../IGameSettings.h" +#include "../../bonuses/Limiters.h" +#include "../../bonuses/Updaters.h" +#include "../../json/JsonBonus.h" +#include "../../json/JsonUtils.h" +#include "../../modding/IdentifierStorage.h" +#include "../../texts/CGeneralTextHandler.h" +#include "../../texts/CLegacyConfigParser.h" VCMI_LIB_NAMESPACE_BEGIN -CHero::CHero() = default; -CHero::~CHero() = default; - -int32_t CHero::getIndex() const -{ - return ID.getNum(); -} - -int32_t CHero::getIconIndex() const -{ - return imageIndex; -} - -std::string CHero::getJsonKey() const -{ - return modScope + ':' + identifier; -} - -std::string CHero::getModScope() const -{ - return modScope; -} - -HeroTypeID CHero::getId() const -{ - return ID; -} - -std::string CHero::getNameTranslated() const -{ - return VLC->generaltexth->translate(getNameTextID()); -} - -std::string CHero::getBiographyTranslated() const -{ - return VLC->generaltexth->translate(getBiographyTextID()); -} - -std::string CHero::getSpecialtyNameTranslated() const -{ - return VLC->generaltexth->translate(getSpecialtyNameTextID()); -} - -std::string CHero::getSpecialtyDescriptionTranslated() const -{ - return VLC->generaltexth->translate(getSpecialtyDescriptionTextID()); -} - -std::string CHero::getSpecialtyTooltipTranslated() const -{ - return VLC->generaltexth->translate(getSpecialtyTooltipTextID()); -} - -std::string CHero::getNameTextID() const -{ - return TextIdentifier("hero", modScope, identifier, "name").get(); -} - -std::string CHero::getBiographyTextID() const -{ - return TextIdentifier("hero", modScope, identifier, "biography").get(); -} - -std::string CHero::getSpecialtyNameTextID() const -{ - return TextIdentifier("hero", modScope, identifier, "specialty", "name").get(); -} - -std::string CHero::getSpecialtyDescriptionTextID() const -{ - return TextIdentifier("hero", modScope, identifier, "specialty", "description").get(); -} - -std::string CHero::getSpecialtyTooltipTextID() const -{ - return TextIdentifier("hero", modScope, identifier, "specialty", "tooltip").get(); -} - -void CHero::registerIcons(const IconRegistar & cb) const -{ - cb(getIconIndex(), 0, "UN32", iconSpecSmall); - cb(getIconIndex(), 0, "UN44", iconSpecLarge); - cb(getIconIndex(), 0, "PORTRAITSLARGE", portraitLarge); - cb(getIconIndex(), 0, "PORTRAITSSMALL", portraitSmall); -} - -void CHero::updateFrom(const JsonNode & data) -{ - //todo: CHero::updateFrom -} - -void CHero::serializeJson(JsonSerializeFormat & handler) -{ - -} - - -SecondarySkill CHeroClass::chooseSecSkill(const std::set & possibles, vstd::RNG & rand) const //picks secondary skill out from given possibilities -{ - assert(!possibles.empty()); - - if (possibles.size() == 1) - return *possibles.begin(); - - int totalProb = 0; - for(const auto & possible : possibles) - if (secSkillProbability.count(possible) != 0) - totalProb += secSkillProbability.at(possible); - - if (totalProb == 0) // may trigger if set contains only banned skills (0 probability) - return *RandomGeneratorUtil::nextItem(possibles, rand); - - auto ran = rand.nextInt(totalProb - 1); - for(const auto & possible : possibles) - { - if (secSkillProbability.count(possible) != 0) - ran -= secSkillProbability.at(possible); - - if(ran < 0) - return possible; - } - - assert(0); // should not be possible - return *possibles.begin(); -} - -bool CHeroClass::isMagicHero() const -{ - return affinity == MAGIC; -} - -int CHeroClass::tavernProbability(FactionID targetFaction) const -{ - auto it = selectionProbability.find(targetFaction); - if (it != selectionProbability.end()) - return it->second; - return 0; -} - -EAlignment CHeroClass::getAlignment() const -{ - return VLC->factions()->getById(faction)->getAlignment(); -} - -int32_t CHeroClass::getIndex() const -{ - return id.getNum(); -} - -int32_t CHeroClass::getIconIndex() const -{ - return getIndex(); -} - -std::string CHeroClass::getJsonKey() const -{ - return modScope + ':' + identifier; -} - -std::string CHeroClass::getModScope() const -{ - return modScope; -} - -HeroClassID CHeroClass::getId() const -{ - return id; -} - -void CHeroClass::registerIcons(const IconRegistar & cb) const -{ - -} - -std::string CHeroClass::getNameTranslated() const -{ - return VLC->generaltexth->translate(getNameTextID()); -} - -std::string CHeroClass::getNameTextID() const -{ - return TextIdentifier("heroClass", modScope, identifier, "name").get(); -} - -void CHeroClass::updateFrom(const JsonNode & data) -{ - //TODO: CHeroClass::updateFrom -} - -void CHeroClass::serializeJson(JsonSerializeFormat & handler) -{ - -} - -CHeroClass::CHeroClass(): - faction(0), - affinity(0), - defaultTavernChance(0) -{ -} - -void CHeroClassHandler::fillPrimarySkillData(const JsonNode & node, CHeroClass * heroClass, PrimarySkill pSkill) const -{ - const auto & skillName = NPrimarySkill::names[pSkill.getNum()]; - auto currentPrimarySkillValue = static_cast(node["primarySkills"][skillName].Integer()); - int primarySkillLegalMinimum = VLC->engineSettings()->getVector(EGameSettings::HEROES_MINIMAL_PRIMARY_SKILLS)[pSkill.getNum()]; - - if(currentPrimarySkillValue < primarySkillLegalMinimum) - { - logMod->error("Hero class '%s' has incorrect initial value '%d' for skill '%s'. Value '%d' will be used instead.", - heroClass->getNameTranslated(), currentPrimarySkillValue, skillName, primarySkillLegalMinimum); - currentPrimarySkillValue = primarySkillLegalMinimum; - } - heroClass->primarySkillInitial.push_back(currentPrimarySkillValue); - heroClass->primarySkillLowLevel.push_back(static_cast(node["lowLevelChance"][skillName].Float())); - heroClass->primarySkillHighLevel.push_back(static_cast(node["highLevelChance"][skillName].Float())); -} - -const std::vector & CHeroClassHandler::getTypeNames() const -{ - static const std::vector typeNames = { "heroClass" }; - return typeNames; -} - -std::shared_ptr CHeroClassHandler::loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) -{ - assert(identifier.find(':') == std::string::npos); - assert(!scope.empty()); - - std::string affinityStr[2] = { "might", "magic" }; - - auto heroClass = std::make_shared(); - - heroClass->id = HeroClassID(index); - heroClass->identifier = identifier; - heroClass->modScope = scope; - heroClass->imageBattleFemale = AnimationPath::fromJson(node["animation"]["battle"]["female"]); - heroClass->imageBattleMale = AnimationPath::fromJson(node["animation"]["battle"]["male"]); - //MODS COMPATIBILITY FOR 0.96 - heroClass->imageMapFemale = node["animation"]["map"]["female"].String(); - heroClass->imageMapMale = node["animation"]["map"]["male"].String(); - - VLC->generaltexth->registerString(scope, heroClass->getNameTextID(), node["name"].String()); - - if (vstd::contains(affinityStr, node["affinity"].String())) - { - heroClass->affinity = vstd::find_pos(affinityStr, node["affinity"].String()); - } - else - { - logGlobal->error("Mod '%s', hero class '%s': invalid affinity '%s'! Expected 'might' or 'magic'!", scope, identifier, node["affinity"].String()); - heroClass->affinity = CHeroClass::MIGHT; - } - - fillPrimarySkillData(node, heroClass.get(), PrimarySkill::ATTACK); - fillPrimarySkillData(node, heroClass.get(), PrimarySkill::DEFENSE); - fillPrimarySkillData(node, heroClass.get(), PrimarySkill::SPELL_POWER); - fillPrimarySkillData(node, heroClass.get(), PrimarySkill::KNOWLEDGE); - - auto percentSumm = std::accumulate(heroClass->primarySkillLowLevel.begin(), heroClass->primarySkillLowLevel.end(), 0); - if(percentSumm <= 0) - logMod->error("Hero class %s has wrong lowLevelChance values: must be above zero!", heroClass->identifier, percentSumm); - - percentSumm = std::accumulate(heroClass->primarySkillHighLevel.begin(), heroClass->primarySkillHighLevel.end(), 0); - if(percentSumm <= 0) - logMod->error("Hero class %s has wrong highLevelChance values: must be above zero!", heroClass->identifier, percentSumm); - - for(auto skillPair : node["secondarySkills"].Struct()) - { - int probability = static_cast(skillPair.second.Integer()); - VLC->identifiers()->requestIdentifier(skillPair.second.getModScope(), "skill", skillPair.first, [heroClass, probability](si32 skillID) - { - heroClass->secSkillProbability[skillID] = probability; - }); - } - - VLC->identifiers()->requestIdentifier ("creature", node["commander"], - [=](si32 commanderID) - { - heroClass->commander = CreatureID(commanderID); - }); - - heroClass->defaultTavernChance = static_cast(node["defaultTavern"].Float()); - for(const auto & tavern : node["tavern"].Struct()) - { - int value = static_cast(tavern.second.Float()); - - VLC->identifiers()->requestIdentifier(tavern.second.getModScope(), "faction", tavern.first, - [=](si32 factionID) - { - heroClass->selectionProbability[FactionID(factionID)] = value; - }); - } - - VLC->identifiers()->requestIdentifier("faction", node["faction"], - [=](si32 factionID) - { - heroClass->faction.setNum(factionID); - }); - - VLC->identifiers()->requestIdentifier(scope, "object", "hero", [=](si32 index) - { - JsonNode classConf = node["mapObject"]; - classConf["heroClass"].String() = identifier; - if (!node["compatibilityIdentifiers"].isNull()) - classConf["compatibilityIdentifiers"] = node["compatibilityIdentifiers"]; - classConf.setModScope(scope); - VLC->objtypeh->loadSubObject(identifier, classConf, index, heroClass->getIndex()); - }); - - return heroClass; -} - -std::vector CHeroClassHandler::loadLegacyData() -{ - size_t dataSize = VLC->engineSettings()->getInteger(EGameSettings::TEXTS_HERO_CLASS); - - objects.resize(dataSize); - std::vector h3Data; - h3Data.reserve(dataSize); - - CLegacyConfigParser parser(TextPath::builtin("DATA/HCTRAITS.TXT")); - - parser.endLine(); // header - parser.endLine(); - - for (size_t i=0; i set selection probability if it was not set before in tavern entries - for(auto & heroClass : objects) - { - for(auto & faction : VLC->townh->objects) - { - if (!faction->town) - continue; - if (heroClass->selectionProbability.count(faction->getId())) - continue; - - auto chance = static_cast(heroClass->defaultTavernChance * faction->town->defaultTavernChance); - heroClass->selectionProbability[faction->getId()] = static_cast(sqrt(chance) + 0.5); //FIXME: replace with std::round once MVS supports it - } - - // set default probabilities for gaining secondary skills where not loaded previously - for(int skillID = 0; skillID < VLC->skillh->size(); skillID++) - { - if(heroClass->secSkillProbability.count(skillID) == 0) - { - const CSkill * skill = (*VLC->skillh)[SecondarySkill(skillID)]; - logMod->trace("%s: no probability for %s, using default", heroClass->identifier, skill->getJsonKey()); - heroClass->secSkillProbability[skillID] = skill->gainChance[heroClass->affinity]; - } - } - } - - for(const auto & hc : objects) - { - if(!hc->imageMapMale.empty()) - { - JsonNode templ; - templ["animation"].String() = hc->imageMapMale; - VLC->objtypeh->getHandlerFor(Obj::HERO, hc->getIndex())->addTemplate(templ); - } - } -} - -CHeroClassHandler::~CHeroClassHandler() = default; - CHeroHandler::~CHeroHandler() = default; CHeroHandler::CHeroHandler() diff --git a/lib/entities/hero/CHeroHandler.h b/lib/entities/hero/CHeroHandler.h new file mode 100644 index 000000000..d62911599 --- /dev/null +++ b/lib/entities/hero/CHeroHandler.h @@ -0,0 +1,59 @@ +/* + * CHeroHandler.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include + +#include "CHero.h" // convenience include - users of handler generally also use its entity + + +#include "../../GameConstants.h" +#include "../../IHandlerBase.h" + +VCMI_LIB_NAMESPACE_BEGIN + +class DLL_LINKAGE CHeroHandler : public CHandlerBase +{ + /// expPerLEvel[i] is amount of exp needed to reach level i; + /// consists of 196 values. Any higher levels require experience larger that TExpType can hold + std::vector expPerLevel; + + /// helpers for loading to avoid huge load functions + void loadHeroArmy(CHero * hero, const JsonNode & node) const; + void loadHeroSkills(CHero * hero, const JsonNode & node) const; + void loadHeroSpecialty(CHero * hero, const JsonNode & node); + + void loadExperience(); + + std::vector> callAfterLoadFinalization; + +public: + ui32 level(TExpType experience) const; //calculates level corresponding to given experience amount + TExpType reqExp(ui32 level) const; //calculates experience required for given level + ui32 maxSupportedLevel() const; + + std::vector loadLegacyData() override; + + void beforeValidate(JsonNode & object) override; + void loadObject(std::string scope, std::string name, const JsonNode & data) override; + void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override; + void afterLoadFinalization() override; + + CHeroHandler(); + ~CHeroHandler(); + + std::set getDefaultAllowed() const; + +protected: + const std::vector & getTypeNames() const override; + std::shared_ptr loadFromJson(const std::string & scope, const JsonNode & node, const std::string & identifier, size_t index) override; +}; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/entities/hero/EHeroGender.h b/lib/entities/hero/EHeroGender.h new file mode 100644 index 000000000..2b9dfb61f --- /dev/null +++ b/lib/entities/hero/EHeroGender.h @@ -0,0 +1,21 @@ +/* + * EHeroGender.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +VCMI_LIB_NAMESPACE_BEGIN + + enum class EHeroGender : int8_t +{ + DEFAULT = -1, // from h3m, instance has same gender as hero type + MALE = 0, + FEMALE = 1, +}; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index 7bba1770d..1ef3d9a12 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -18,7 +18,6 @@ #include "../ArtifactUtils.h" #include "../texts/CGeneralTextHandler.h" -#include "../CHeroHandler.h" #include "../CPlayerState.h" #include "../CStopWatch.h" #include "../IGameSettings.h" @@ -30,6 +29,8 @@ #include "../campaign/CampaignState.h" #include "../constants/StringConstants.h" #include "../entities/faction/CTownHandler.h" +#include "../entities/hero/CHero.h" +#include "../entities/hero/CHeroClass.h" #include "../filesystem/ResourcePath.h" #include "../json/JsonBonus.h" #include "../json/JsonUtils.h" diff --git a/lib/gameState/CGameStateCampaign.cpp b/lib/gameState/CGameStateCampaign.cpp index 2178da654..80fc536f7 100644 --- a/lib/gameState/CGameStateCampaign.cpp +++ b/lib/gameState/CGameStateCampaign.cpp @@ -16,6 +16,8 @@ #include "../campaign/CampaignState.h" #include "../entities/building/CBuilding.h" #include "../entities/building/CBuildingHandler.h" +#include "../entities/hero/CHeroClass.h" +#include "../entities/hero/CHero.h" #include "../mapping/CMapEditManager.h" #include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGTownInstance.h" @@ -23,13 +25,13 @@ #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../StartInfo.h" -#include "../CHeroHandler.h" #include "../mapping/CMap.h" #include "../ArtifactUtils.h" #include "../CPlayerState.h" #include "../serializer/CMemorySerializer.h" #include +#include VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/gameState/GameStatistics.cpp b/lib/gameState/GameStatistics.cpp index 6e1c95e85..a6ee5041c 100644 --- a/lib/gameState/GameStatistics.cpp +++ b/lib/gameState/GameStatistics.cpp @@ -14,7 +14,6 @@ #include "../VCMIDirs.h" #include "CGameState.h" #include "TerrainHandler.h" -#include "CHeroHandler.h" #include "StartInfo.h" #include "HighScore.h" #include "../mapObjects/CGHeroInstance.h" diff --git a/lib/gameState/InfoAboutArmy.cpp b/lib/gameState/InfoAboutArmy.cpp index cb6ad5e95..54e8528a8 100644 --- a/lib/gameState/InfoAboutArmy.cpp +++ b/lib/gameState/InfoAboutArmy.cpp @@ -12,7 +12,9 @@ #include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGTownInstance.h" -#include "../CHeroHandler.h" + +#include +#include VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/gameState/TavernHeroesPool.cpp b/lib/gameState/TavernHeroesPool.cpp index 44d085c13..3c0dfadbf 100644 --- a/lib/gameState/TavernHeroesPool.cpp +++ b/lib/gameState/TavernHeroesPool.cpp @@ -11,7 +11,6 @@ #include "TavernHeroesPool.h" #include "../mapObjects/CGHeroInstance.h" -#include "../CHeroHandler.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/json/JsonRandom.cpp b/lib/json/JsonRandom.cpp index 57f7a97a2..bfc65fa9d 100644 --- a/lib/json/JsonRandom.cpp +++ b/lib/json/JsonRandom.cpp @@ -13,6 +13,8 @@ #include #include +#include +#include #include "JsonBonus.h" @@ -23,8 +25,9 @@ #include "../CCreatureSet.h" #include "../spells/CSpellHandler.h" #include "../CSkillHandler.h" -#include "../CHeroHandler.h" #include "../IGameCallback.h" +#include "../entities/hero/CHero.h" +#include "../entities/hero/CHeroClass.h" #include "../gameState/CGameState.h" #include "../mapObjects/IObjectInterface.h" #include "../modding/IdentifierStorage.h" diff --git a/lib/mapObjectConstructors/CommonConstructors.cpp b/lib/mapObjectConstructors/CommonConstructors.cpp index 421d2565f..b8194937c 100644 --- a/lib/mapObjectConstructors/CommonConstructors.cpp +++ b/lib/mapObjectConstructors/CommonConstructors.cpp @@ -11,7 +11,6 @@ #include "CommonConstructors.h" #include "../texts/CGeneralTextHandler.h" -#include "../CHeroHandler.h" #include "../IGameCallback.h" #include "../json/JsonRandom.h" #include "../constants/StringConstants.h" @@ -19,6 +18,7 @@ #include "../VCMI_Lib.h" #include "../entities/faction/CTownHandler.h" +#include "../entities/hero/CHeroClass.h" #include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGMarket.h" #include "../mapObjects/CGTownInstance.h" diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index b31ff4190..e7825b324 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -17,7 +17,6 @@ #include "../texts/CGeneralTextHandler.h" #include "../ArtifactUtils.h" -#include "../CHeroHandler.h" #include "../TerrainHandler.h" #include "../RoadHandler.h" #include "../IGameSettings.h" @@ -31,6 +30,8 @@ #include "../StartInfo.h" #include "CGTownInstance.h" #include "../entities/faction/CTownHandler.h" +#include "../entities/hero/CHeroHandler.h" +#include "../entities/hero/CHeroClass.h" #include "../battle/CBattleInfoEssentials.h" #include "../campaign/CampaignState.h" #include "../json/JsonBonus.h" diff --git a/lib/mapObjects/CGHeroInstance.h b/lib/mapObjects/CGHeroInstance.h index ebb8261f8..aafad435c 100644 --- a/lib/mapObjects/CGHeroInstance.h +++ b/lib/mapObjects/CGHeroInstance.h @@ -14,6 +14,7 @@ #include "CArmedInstance.h" #include "IOwnableObject.h" +#include "../entities/hero/EHeroGender.h" #include "../CArtHandler.h" // For CArtifactSet VCMI_LIB_NAMESPACE_BEGIN @@ -24,7 +25,6 @@ class CGTownInstance; class CMap; struct TerrainTile; struct TurnInfo; -enum class EHeroGender : int8_t; class DLL_LINKAGE CGHeroPlaceholder : public CGObjectInstance { diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 051349282..1cc466324 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -16,9 +16,9 @@ #include "../ArtifactUtils.h" #include "../CSoundBase.h" #include "../texts/CGeneralTextHandler.h" -#include "../CHeroHandler.h" #include "CGCreature.h" #include "../IGameCallback.h" +#include "../entities/hero/CHeroHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../serializer/JsonSerializeFormat.h" #include "../GameConstants.h" diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 57e3a4c24..373bb3fc4 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -13,11 +13,11 @@ #include "../CArtHandler.h" #include "../VCMI_Lib.h" #include "../CCreatureHandler.h" -#include "../CHeroHandler.h" #include "../GameSettings.h" #include "../RiverHandler.h" #include "../RoadHandler.h" #include "../TerrainHandler.h" +#include "../entities/hero/CHeroHandler.h" #include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CGTownInstance.h" #include "../mapObjects/CQuest.h" diff --git a/lib/mapping/CMapHeader.cpp b/lib/mapping/CMapHeader.cpp index ec9c74df8..66ed48dbd 100644 --- a/lib/mapping/CMapHeader.cpp +++ b/lib/mapping/CMapHeader.cpp @@ -12,9 +12,9 @@ #include "MapFormat.h" -#include "../CHeroHandler.h" #include "../VCMI_Lib.h" #include "../entities/faction/CTownHandler.h" +#include "../entities/hero/CHeroHandler.h" #include "../json/JsonUtils.h" #include "../modding/CModHandler.h" #include "../texts/CGeneralTextHandler.h" diff --git a/lib/mapping/CMapInfo.cpp b/lib/mapping/CMapInfo.cpp index 74ee2cd44..a13084ac9 100644 --- a/lib/mapping/CMapInfo.cpp +++ b/lib/mapping/CMapInfo.cpp @@ -25,7 +25,6 @@ #include "../texts/TextOperations.h" #include "../CCreatureHandler.h" #include "../IGameSettings.h" -#include "../CHeroHandler.h" #include "../CConfigHandler.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 1fe7da29f..16e02db92 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -18,7 +18,6 @@ #include "../ArtifactUtils.h" #include "../CCreatureHandler.h" #include "../texts/CGeneralTextHandler.h" -#include "../CHeroHandler.h" #include "../CSkillHandler.h" #include "../CStopWatch.h" #include "../IGameSettings.h" @@ -27,6 +26,7 @@ #include "../TerrainHandler.h" #include "../VCMI_Lib.h" #include "../constants/StringConstants.h" +#include "../entities/hero/CHeroHandler.h" #include "../filesystem/CBinaryReader.h" #include "../filesystem/Filesystem.h" #include "../mapObjectConstructors/AObjectTypeHandler.h" diff --git a/lib/mapping/MapFormatJson.cpp b/lib/mapping/MapFormatJson.cpp index 0777defed..efbce4560 100644 --- a/lib/mapping/MapFormatJson.cpp +++ b/lib/mapping/MapFormatJson.cpp @@ -17,12 +17,12 @@ #include "CMap.h" #include "MapFormat.h" #include "../ArtifactUtils.h" -#include "../CHeroHandler.h" #include "../VCMI_Lib.h" #include "../RiverHandler.h" #include "../RoadHandler.h" #include "../TerrainHandler.h" #include "../entities/faction/CTownHandler.h" +#include "../entities/hero/CHeroHandler.h" #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapObjects/ObjectTemplate.h" diff --git a/lib/mapping/MapIdentifiersH3M.cpp b/lib/mapping/MapIdentifiersH3M.cpp index 3e093227b..e75e58235 100644 --- a/lib/mapping/MapIdentifiersH3M.cpp +++ b/lib/mapping/MapIdentifiersH3M.cpp @@ -12,7 +12,6 @@ #include "MapIdentifiersH3M.h" #include "../VCMI_Lib.h" -#include "../CHeroHandler.h" #include "../entities/faction/CFaction.h" #include "../entities/faction/CTownHandler.h" #include "../filesystem/Filesystem.h" diff --git a/lib/modding/ContentTypeHandler.cpp b/lib/modding/ContentTypeHandler.cpp index 0a9acb0f4..18f2605ff 100644 --- a/lib/modding/ContentTypeHandler.cpp +++ b/lib/modding/ContentTypeHandler.cpp @@ -19,8 +19,9 @@ #include "../CCreatureHandler.h" #include "../CConfigHandler.h" #include "../entities/faction/CTownHandler.h" +#include "../entities/hero/CHeroClassHandler.h" +#include "../entities/hero/CHeroHandler.h" #include "../texts/CGeneralTextHandler.h" -#include "../CHeroHandler.h" #include "../CSkillHandler.h" #include "../CStopWatch.h" #include "../IGameSettings.h" diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 6ea83ab8f..6ef830fdb 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -20,7 +20,6 @@ #include "NetPackVisitor.h" #include "texts/CGeneralTextHandler.h" #include "CArtHandler.h" -#include "CHeroHandler.h" #include "VCMI_Lib.h" #include "mapping/CMap.h" #include "spells/CSpellHandler.h" diff --git a/lib/rewardable/Interface.cpp b/lib/rewardable/Interface.cpp index f67250efe..7bef36108 100644 --- a/lib/rewardable/Interface.cpp +++ b/lib/rewardable/Interface.cpp @@ -11,10 +11,10 @@ #include "StdInc.h" #include "Interface.h" -#include "../CHeroHandler.h" #include "../TerrainHandler.h" #include "../CPlayerState.h" #include "../CSoundBase.h" +#include "../entities/hero/CHeroHandler.h" #include "../gameState/CGameState.h" #include "../spells/CSpellHandler.h" #include "../spells/ISpellMechanics.h" diff --git a/lib/rewardable/Limiter.cpp b/lib/rewardable/Limiter.cpp index 384ffea92..5e0d4bd80 100644 --- a/lib/rewardable/Limiter.cpp +++ b/lib/rewardable/Limiter.cpp @@ -17,7 +17,6 @@ #include "../networkPacks/Component.h" #include "../serializer/JsonSerializeFormat.h" #include "../constants/StringConstants.h" -#include "../CHeroHandler.h" #include "../CSkillHandler.h" #include "../ArtifactUtils.h" diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index 0e02212b9..c33a10dd4 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -17,11 +17,11 @@ #include "../CRandomGenerator.h" #include "../entities/faction/CTownHandler.h" #include "../entities/faction/CFaction.h" +#include "../entities/hero/CHero.h" #include "../mapObjectConstructors/AObjectTypeHandler.h" #include "../mapObjectConstructors/CObjectClassesHandler.h" #include "../mapping/CMapEditManager.h" #include "../CArtHandler.h" -#include "../CHeroHandler.h" #include "../constants/StringConstants.h" #include "../filesystem/Filesystem.h" #include "CZonePlacer.h" @@ -35,6 +35,7 @@ #include "modificators/RoadPlacer.h" #include +#include VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/serializer/CSerializer.cpp b/lib/serializer/CSerializer.cpp index f8311a95b..3e7e84a6f 100644 --- a/lib/serializer/CSerializer.cpp +++ b/lib/serializer/CSerializer.cpp @@ -10,9 +10,9 @@ #include "StdInc.h" #include "CSerializer.h" +#include "../entities/hero/CHero.h" #include "../gameState/CGameState.h" #include "../mapping/CMap.h" -#include "../CHeroHandler.h" #include "../mapObjects/CGHeroInstance.h" #include "../mapObjects/CQuest.h" diff --git a/lib/serializer/RegisterTypes.h b/lib/serializer/RegisterTypes.h index 492d0e371..204d99432 100644 --- a/lib/serializer/RegisterTypes.h +++ b/lib/serializer/RegisterTypes.h @@ -9,7 +9,6 @@ */ #pragma once -#include "../CHeroHandler.h" #include "../CPlayerState.h" #include "../CStack.h" #include "../battle/BattleInfo.h" diff --git a/lib/serializer/SerializerReflection.cpp b/lib/serializer/SerializerReflection.cpp index 4862c62b7..ecb3427b8 100644 --- a/lib/serializer/SerializerReflection.cpp +++ b/lib/serializer/SerializerReflection.cpp @@ -19,6 +19,7 @@ #include "../RiverHandler.h" #include "../RoadHandler.h" #include "../TerrainHandler.h" +#include "../entities/hero/CHero.h" #include "../mapObjects/ObjectTemplate.h" #include "../mapping/CMapInfo.h" #include "../rmg/CMapGenOptions.h" diff --git a/lib/spells/BonusCaster.cpp b/lib/spells/BonusCaster.cpp index deb119a89..a2d8523b1 100644 --- a/lib/spells/BonusCaster.cpp +++ b/lib/spells/BonusCaster.cpp @@ -12,12 +12,12 @@ #include "BonusCaster.h" #include +#include #include "../battle/Unit.h" #include "../bonuses/Bonus.h" #include "../VCMI_Lib.h" #include "../CSkillHandler.h" -#include "../CHeroHandler.h" VCMI_LIB_NAMESPACE_BEGIN diff --git a/lib/spells/ISpellMechanics.cpp b/lib/spells/ISpellMechanics.cpp index a1488e1e8..24f40b067 100644 --- a/lib/spells/ISpellMechanics.cpp +++ b/lib/spells/ISpellMechanics.cpp @@ -36,7 +36,6 @@ #include "CSpellHandler.h" -#include "../CHeroHandler.h"//todo: remove #include "../IGameCallback.h"//todo: remove #include "../BattleFieldHandler.h" diff --git a/lib/spells/effects/Summon.cpp b/lib/spells/effects/Summon.cpp index e46cdc6da..e4d51bd5b 100644 --- a/lib/spells/effects/Summon.cpp +++ b/lib/spells/effects/Summon.cpp @@ -18,7 +18,6 @@ #include "../../battle/Unit.h" #include "../../serializer/JsonSerializeFormat.h" #include "../../CCreatureHandler.h" -#include "../../CHeroHandler.h" #include "../../mapObjects/CGHeroInstance.h" #include "../../networkPacks/PacksForClientBattle.h" diff --git a/lib/texts/TextLocalizationContainer.cpp b/lib/texts/TextLocalizationContainer.cpp index f45898cf7..0a5c8aa36 100644 --- a/lib/texts/TextLocalizationContainer.cpp +++ b/lib/texts/TextLocalizationContainer.cpp @@ -107,7 +107,7 @@ void TextLocalizationContainer::registerString(const std::string & identifierMod assert(!identifierModContext.empty()); assert(!localizedStringModContext.empty()); assert(UID.get().find("..") == std::string::npos); // invalid identifier - there is section that was evaluated to empty string - assert(stringsLocalizations.count(UID.get()) == 0 || identifierModContext == "map"); // registering already registered string? + assert(stringsLocalizations.count(UID.get()) == 0 || boost::algorithm::starts_with(UID.get(), "map")); // registering already registered string? if(stringsLocalizations.count(UID.get()) > 0) { diff --git a/mapeditor/graphics.cpp b/mapeditor/graphics.cpp index 3ca8bd4a9..33dfb8b4d 100644 --- a/mapeditor/graphics.cpp +++ b/mapeditor/graphics.cpp @@ -29,11 +29,11 @@ #include "../lib/texts/CGeneralTextHandler.h" #include "BitmapHandler.h" #include "../lib/CStopWatch.h" +#include "../lib/entities/hero/CHeroClassHandler.h" #include "../lib/mapObjectConstructors/AObjectTypeHandler.h" #include "../lib/mapObjectConstructors/CObjectClassesHandler.h" #include "../lib/mapObjects/CGObjectInstance.h" #include "../lib/mapObjects/ObjectTemplate.h" -#include "../lib/CHeroHandler.h" Graphics * graphics = nullptr; diff --git a/mapeditor/inspector/inspector.cpp b/mapeditor/inspector/inspector.cpp index 4ad9c5eaf..f8a651325 100644 --- a/mapeditor/inspector/inspector.cpp +++ b/mapeditor/inspector/inspector.cpp @@ -11,8 +11,9 @@ #include "inspector.h" #include "../lib/ArtifactUtils.h" #include "../lib/CArtHandler.h" +#include "../lib/entities/hero/CHeroClass.h" +#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/spells/CSpellHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/CRandomGenerator.h" #include "../lib/mapObjectConstructors/AObjectTypeHandler.h" #include "../lib/mapObjectConstructors/CObjectClassesHandler.h" diff --git a/mapeditor/inspector/portraitwidget.cpp b/mapeditor/inspector/portraitwidget.cpp index 669bb880c..af113be2e 100644 --- a/mapeditor/inspector/portraitwidget.cpp +++ b/mapeditor/inspector/portraitwidget.cpp @@ -10,8 +10,8 @@ #include "StdInc.h" #include "portraitwidget.h" #include "ui_portraitwidget.h" -#include "../../lib/CHeroHandler.h" #include "../Animation.h" +#include "../lib/entities/hero/CHeroHandler.h" PortraitWidget::PortraitWidget(CGHeroInstance & h, QWidget *parent): QDialog(parent), diff --git a/mapeditor/inspector/questwidget.cpp b/mapeditor/inspector/questwidget.cpp index df706c19d..8edd018de 100644 --- a/mapeditor/inspector/questwidget.cpp +++ b/mapeditor/inspector/questwidget.cpp @@ -16,12 +16,16 @@ #include "../lib/spells/CSpellHandler.h" #include "../lib/CArtHandler.h" #include "../lib/CCreatureHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/constants/StringConstants.h" #include "../lib/mapping/CMap.h" #include "../lib/mapObjects/CGHeroInstance.h" #include "../lib/mapObjects/CGCreature.h" +#include +#include +#include +#include + QuestWidget::QuestWidget(MapController & _controller, CQuest & _sh, QWidget *parent) : QDialog(parent), controller(_controller), diff --git a/mapeditor/inspector/rewardswidget.cpp b/mapeditor/inspector/rewardswidget.cpp index 4a8d7ab4c..b4710ff88 100644 --- a/mapeditor/inspector/rewardswidget.cpp +++ b/mapeditor/inspector/rewardswidget.cpp @@ -13,7 +13,6 @@ #include "../lib/VCMI_Lib.h" #include "../lib/CSkillHandler.h" #include "../lib/spells/CSpellHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/CArtHandler.h" #include "../lib/CCreatureHandler.h" #include "../lib/constants/StringConstants.h" @@ -24,6 +23,11 @@ #include "../lib/mapObjects/CGPandoraBox.h" #include "../lib/mapObjects/CQuest.h" +#include +#include +#include +#include + RewardsWidget::RewardsWidget(CMap & m, CRewardableObject & p, QWidget *parent) : QDialog(parent), map(m), diff --git a/mapeditor/mapcontroller.cpp b/mapeditor/mapcontroller.cpp index a30a90aa8..0afe214d1 100644 --- a/mapeditor/mapcontroller.cpp +++ b/mapeditor/mapcontroller.cpp @@ -13,6 +13,8 @@ #include "../lib/ArtifactUtils.h" #include "../lib/GameConstants.h" +#include "../lib/entities/hero/CHeroClass.h" +#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/mapObjectConstructors/AObjectTypeHandler.h" #include "../lib/mapObjectConstructors/CObjectClassesHandler.h" #include "../lib/mapObjects/ObjectTemplate.h" @@ -25,7 +27,6 @@ #include "../lib/TerrainHandler.h" #include "../lib/CSkillHandler.h" #include "../lib/spells/CSpellHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/CRandomGenerator.h" #include "../lib/serializer/CMemorySerializer.h" #include "mapview.h" diff --git a/mapeditor/maphandler.cpp b/mapeditor/maphandler.cpp index c9b18ac32..70aac50b0 100644 --- a/mapeditor/maphandler.cpp +++ b/mapeditor/maphandler.cpp @@ -19,7 +19,6 @@ #include "../lib/mapObjects/CGHeroInstance.h" #include "../lib/mapObjects/ObjectTemplate.h" #include "../lib/mapObjects/MiscObjects.h" -#include "../lib/CHeroHandler.h" #include "../lib/GameConstants.h" const int tileSize = 32; diff --git a/mapeditor/mapsettings/abstractsettings.cpp b/mapeditor/mapsettings/abstractsettings.cpp index f75a77685..a21d2f24b 100644 --- a/mapeditor/mapsettings/abstractsettings.cpp +++ b/mapeditor/mapsettings/abstractsettings.cpp @@ -13,7 +13,6 @@ #include "../mapcontroller.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGCreature.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/mapObjects/CGCreature.h" //parses date for lose condition (1m 1w 1d) diff --git a/mapeditor/mapsettings/mapsettings.cpp b/mapeditor/mapsettings/mapsettings.cpp index 7e579cb81..f94783020 100644 --- a/mapeditor/mapsettings/mapsettings.cpp +++ b/mapeditor/mapsettings/mapsettings.cpp @@ -13,10 +13,10 @@ #include "ui_mapsettings.h" #include "mainwindow.h" -#include "../../lib/CSkillHandler.h" -#include "../../lib/spells/CSpellHandler.h" #include "../../lib/CArtHandler.h" -#include "../../lib/CHeroHandler.h" +#include "../../lib/CSkillHandler.h" +#include "../../lib/entities/hero/CHeroHandler.h" +#include "../../lib/spells/CSpellHandler.h" MapSettings::MapSettings(MapController & ctrl, QWidget *parent) : diff --git a/mapeditor/validator.cpp b/mapeditor/validator.cpp index b4a98df30..17c1d2dcc 100644 --- a/mapeditor/validator.cpp +++ b/mapeditor/validator.cpp @@ -12,12 +12,12 @@ #include "validator.h" #include "mapcontroller.h" #include "ui_validator.h" +#include "../lib/entities/hero/CHero.h" #include "../lib/mapping/CMap.h" #include "../lib/mapObjects/MapObjects.h" #include "../lib/modding/CModHandler.h" #include "../lib/modding/CModInfo.h" #include "../lib/spells/CSpellHandler.h" -#include "../lib/CHeroHandler.h" Validator::Validator(const CMap * map, QWidget *parent) : QDialog(parent), diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1f9549fa0..08d311cbd 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -29,7 +29,6 @@ #include "../lib/CCreatureHandler.h" #include "../lib/CCreatureSet.h" #include "../lib/texts/CGeneralTextHandler.h" -#include "../lib/CHeroHandler.h" #include "../lib/CPlayerState.h" #include "../lib/CRandomGenerator.h" #include "../lib/CSoundBase.h" @@ -48,6 +47,7 @@ #include "../lib/entities/building/CBuilding.h" #include "../lib/entities/faction/CTownHandler.h" +#include "../lib/entities/hero/CHeroHandler.h" #include "../lib/filesystem/FileInfo.h" #include "../lib/filesystem/Filesystem.h" diff --git a/server/CVCMIServer.cpp b/server/CVCMIServer.cpp index c0753d2a1..e69813542 100644 --- a/server/CVCMIServer.cpp +++ b/server/CVCMIServer.cpp @@ -15,9 +15,10 @@ #include "LobbyNetPackVisitors.h" #include "processors/PlayerMessageProcessor.h" -#include "../lib/CHeroHandler.h" #include "../lib/CPlayerState.h" #include "../lib/campaign/CampaignState.h" +#include "../lib/entities/hero/CHeroHandler.h" +#include "../lib/entities/hero/CHeroClass.h" #include "../lib/gameState/CGameState.h" #include "../lib/mapping/CMapDefines.h" #include "../lib/mapping/CMapInfo.h" diff --git a/server/processors/HeroPoolProcessor.cpp b/server/processors/HeroPoolProcessor.cpp index 44a50884a..976c74b6f 100644 --- a/server/processors/HeroPoolProcessor.cpp +++ b/server/processors/HeroPoolProcessor.cpp @@ -14,10 +14,11 @@ #include "../CGameHandler.h" #include "../../lib/CRandomGenerator.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/CPlayerState.h" #include "../../lib/IGameSettings.h" #include "../../lib/StartInfo.h" +#include "../../lib/entities/hero/CHeroClass.h" +#include "../../lib/entities/hero/CHero.h" #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/networkPacks/PacksForClient.h" diff --git a/server/processors/PlayerMessageProcessor.cpp b/server/processors/PlayerMessageProcessor.cpp index 6ebc78375..38b4409d0 100644 --- a/server/processors/PlayerMessageProcessor.cpp +++ b/server/processors/PlayerMessageProcessor.cpp @@ -16,10 +16,10 @@ #include "../CVCMIServer.h" #include "../TurnTimerHandler.h" -#include "../../lib/CHeroHandler.h" #include "../../lib/CPlayerState.h" #include "../../lib/StartInfo.h" #include "../../lib/entities/building/CBuilding.h" +#include "../../lib/entities/hero/CHeroHandler.h" #include "../../lib/gameState/CGameState.h" #include "../../lib/mapObjects/CGTownInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h" diff --git a/test/entity/CHeroClassTest.cpp b/test/entity/CHeroClassTest.cpp index db109ae94..23eb7266b 100644 --- a/test/entity/CHeroClassTest.cpp +++ b/test/entity/CHeroClassTest.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" -#include "../../lib/CHeroHandler.h" +#include "../../lib/entities/hero/CHeroClass.h" namespace test { diff --git a/test/entity/CHeroTest.cpp b/test/entity/CHeroTest.cpp index edea854a5..92f0e190d 100644 --- a/test/entity/CHeroTest.cpp +++ b/test/entity/CHeroTest.cpp @@ -9,7 +9,7 @@ */ #include "StdInc.h" -#include "../../lib/CHeroHandler.h" +#include "../../lib/entities/hero/CHero.h" namespace test { From d43997f5ba68552b1adfd27f616ca395bde7bca6 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Sun, 13 Oct 2024 21:08:43 +0200 Subject: [PATCH 24/69] use sdl mixer to get audio duration --- client/media/CSoundHandler.cpp | 23 ++++++++++++++--------- 1 file changed, 14 insertions(+), 9 deletions(-) diff --git a/client/media/CSoundHandler.cpp b/client/media/CSoundHandler.cpp index 79562f15c..a0b5e6301 100644 --- a/client/media/CSoundHandler.cpp +++ b/client/media/CSoundHandler.cpp @@ -147,18 +147,23 @@ uint32_t CSoundHandler::getSoundDurationMilliseconds(const AudioPath & sound) auto data = CResourceHandler::get()->load(resourcePath)->readAll(); - SDL_AudioSpec spec; - uint32_t audioLen; - uint8_t * audioBuf; uint32_t milliseconds = 0; - if(SDL_LoadWAV_RW(SDL_RWFromMem(data.first.get(), data.second), 1, &spec, &audioBuf, &audioLen) != nullptr) + Mix_Chunk * chunk = Mix_LoadWAV_RW(SDL_RWFromMem(data.first.get(), data.second), 1); + + int freq = 0; + Uint16 fmt = 0; + int chans = 0; + if(!Mix_QuerySpec(&freq, &fmt, &chans)) + return 0; + + if(chunk != nullptr) { - SDL_FreeWAV(audioBuf); - uint32_t sampleSize = SDL_AUDIO_BITSIZE(spec.format) / 8; - uint32_t sampleCount = audioLen / sampleSize; - uint32_t sampleLen = sampleCount / spec.channels; - milliseconds = 1000 * sampleLen / spec.freq; + Uint32 points = (chunk->alen / ((fmt & 0xFF) / 8)); + Uint32 frames = (points / chans); + milliseconds = ((frames * 1000) / freq); + + Mix_FreeChunk(chunk); } return milliseconds; From 024778dfe81cd3614a9eca907275fdf5b3377afa Mon Sep 17 00:00:00 2001 From: Maurycy <55395993+XCOM-HUB@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:18:32 +0200 Subject: [PATCH 25/69] Update swedish.json --- Mods/vcmi/config/vcmi/swedish.json | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/Mods/vcmi/config/vcmi/swedish.json b/Mods/vcmi/config/vcmi/swedish.json index e9145d40f..b5ec96341 100644 --- a/Mods/vcmi/config/vcmi/swedish.json +++ b/Mods/vcmi/config/vcmi/swedish.json @@ -536,7 +536,7 @@ "core.bonus.ADDITIONAL_ATTACK.name" : "Dubbelslag", "core.bonus.ADDITIONAL_ATTACK.description" : "Attackerar två gånger.", "core.bonus.ADDITIONAL_RETALIATION.name" : "Ytterligare motattacker", - "core.bonus.ADDITIONAL_RETALIATION.description" : "Kan slå tillbaka ${val} extra gånger.", + "core.bonus.ADDITIONAL_RETALIATION.description" : "Kan slå tillbaka ${val} extra gång(er).", "core.bonus.AIR_IMMUNITY.name" : "Luft-immunitet", "core.bonus.AIR_IMMUNITY.description" : "Immun mot alla luftmagi-trollformler.", "core.bonus.ATTACKS_ALL_ADJACENT.name" : "Attackera runtomkring", @@ -625,7 +625,7 @@ "core.bonus.NO_DISTANCE_PENALTY.description" : "Gör full skada på alla avstånd i strid.", "core.bonus.NO_MELEE_PENALTY.name" : "Närstridsspecialist", "core.bonus.NO_MELEE_PENALTY.description" : "Ingen närstridsbestraffning.", - "core.bonus.NO_MORALE.name" : "Ingen Moralpåverkan", + "core.bonus.NO_MORALE.name" : "Ingen moralpåverkan", "core.bonus.NO_MORALE.description" : "Immun mot moral-effekter (neutral moral).", "core.bonus.NO_WALL_PENALTY.name" : "Ingen murbestraffning", "core.bonus.NO_WALL_PENALTY.description" : "Gör full skada mot fiender bakom en mur.", @@ -641,14 +641,14 @@ "core.bonus.REBIRTH.description" : "${val}% återuppväcks efter döden.", "core.bonus.RETURN_AFTER_STRIKE.name" : "Återvänder efter närstrid", "core.bonus.RETURN_AFTER_STRIKE.description" : "Återvänder till sin ruta efter attack.", - "core.bonus.REVENGE.name" : "Hämnd", - "core.bonus.REVENGE.description" : "Extra skada om den själv blivit skadad.", + "core.bonus.REVENGE.name" : "Hämndlysten", + "core.bonus.REVENGE.description" : "Vållar mer skada om den själv blivit skadad.", "core.bonus.SHOOTER.name" : "Distans-attack", "core.bonus.SHOOTER.description" : "Varelsen kan skjuta/attackera på avstånd.", "core.bonus.SHOOTS_ALL_ADJACENT.name" : "Skjuter alla i närheten", "core.bonus.SHOOTS_ALL_ADJACENT.description" : "Distans-attack drabbar alla inom räckhåll.", "core.bonus.SOUL_STEAL.name" : "Själtjuv", - "core.bonus.SOUL_STEAL.description" : "Återuppväcker ${val} av sina egna/dödad fiende.", + "core.bonus.SOUL_STEAL.description" : "För varje dödad fiende återuppväcks: ${val}.", "core.bonus.SPELLCASTER.name" : "Besvärjare", "core.bonus.SPELLCASTER.description" : "Kan kasta: ${subtype.spell}.", "core.bonus.SPELL_AFTER_ATTACK.name" : "Besvärja efter attack", From 22d9ad2538617bdf875d9afb2263e2f9081425a7 Mon Sep 17 00:00:00 2001 From: Maurycy <55395993+XCOM-HUB@users.noreply.github.com> Date: Mon, 14 Oct 2024 00:27:59 +0200 Subject: [PATCH 26/69] Update swedish.json --- Mods/vcmi/config/vcmi/swedish.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mods/vcmi/config/vcmi/swedish.json b/Mods/vcmi/config/vcmi/swedish.json index b5ec96341..be905ed40 100644 --- a/Mods/vcmi/config/vcmi/swedish.json +++ b/Mods/vcmi/config/vcmi/swedish.json @@ -662,7 +662,7 @@ "core.bonus.SPELL_LIKE_ATTACK.name" : "Magisk attack", "core.bonus.SPELL_LIKE_ATTACK.description" : "Attackerar med '${subtype.spell}'.", "core.bonus.SPELL_RESISTANCE_AURA.name" : "Motståndsaura", - "core.bonus.SPELL_RESISTANCE_AURA.description" : "Närbelägna förband får ${val}% magi-resistens.", + "core.bonus.SPELL_RESISTANCE_AURA.description" : "Angränsande förband får ${val}% magi-resistens.", "core.bonus.SUMMON_GUARDIANS.name" : "Åkalla väktare", "core.bonus.SUMMON_GUARDIANS.description" : "Vid strid åkallas: ${subtype.creature} ${val}%.", "core.bonus.SYNERGY_TARGET.name" : "Synergibar", From 1e4956d3ea2b5d251e1481e9f4dbaa58bcbc2e24 Mon Sep 17 00:00:00 2001 From: Maurycy <55395993+XCOM-HUB@users.noreply.github.com> Date: Mon, 14 Oct 2024 01:03:18 +0200 Subject: [PATCH 27/69] Update swedish.json --- Mods/vcmi/config/vcmi/swedish.json | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Mods/vcmi/config/vcmi/swedish.json b/Mods/vcmi/config/vcmi/swedish.json index be905ed40..af3c27b82 100644 --- a/Mods/vcmi/config/vcmi/swedish.json +++ b/Mods/vcmi/config/vcmi/swedish.json @@ -243,7 +243,7 @@ "vcmi.adventureOptions.showGrid.hover" : "Visa rutnät", "vcmi.adventureOptions.showGrid.help" : "{Visa rutnät}\n\nVisa rutnätsöverlägget som markerar gränserna mellan äventyrskartans brickor/rutor.", "vcmi.adventureOptions.borderScroll.hover" : "Kantrullning", - "vcmi.adventureOptions.borderScroll.help" : "{Kantrullning}\n\nRullar äventyrskartan när markören är angränsande till fönsterkanten. Kan inaktiveras genom att hålla ned CTRL-tangenten.", + "vcmi.adventureOptions.borderScroll.help" : "{Kantrullning}\n\nRullar äventyrskartan när markören är till fönsterkanten. Kan inaktiveras genom att hålla ned CTRL-tangenten.", "vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Hantera armén i nedre högra hörnet", "vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Varelsehantering i infopanelen}\n\nTillåter omarrangering av varelser i infopanelen längst ner till höger på äventyrskartan istället för att bläddra mellan olika infopaneler.", "vcmi.adventureOptions.leftButtonDrag.hover" : "V.klicksdragning", @@ -670,7 +670,7 @@ "core.bonus.TWO_HEX_ATTACK_BREATH.name" : "Dödlig andedräkt", "core.bonus.TWO_HEX_ATTACK_BREATH.description" : "Andningsattack (2 rutors räckvidd).", "core.bonus.THREE_HEADED_ATTACK.name" : "Trehövdad attack", - "core.bonus.THREE_HEADED_ATTACK.description" : "Attackerar tre angränsande enheter.", + "core.bonus.THREE_HEADED_ATTACK.description" : "Attackerar upp till tre enheter framför sig.", "core.bonus.TRANSMUTATION.name" : "Transmutation", "core.bonus.TRANSMUTATION.description" : "${val}% chans att förvandla angripen enhet.", "core.bonus.UNDEAD.name" : "Odöd", From bbe216c51a11422e79940dce65f716dfacb847d6 Mon Sep 17 00:00:00 2001 From: Maurycy <55395993+XCOM-HUB@users.noreply.github.com> Date: Mon, 14 Oct 2024 01:20:56 +0200 Subject: [PATCH 28/69] Update swedish.json --- Mods/vcmi/config/vcmi/swedish.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mods/vcmi/config/vcmi/swedish.json b/Mods/vcmi/config/vcmi/swedish.json index af3c27b82..b04096f46 100644 --- a/Mods/vcmi/config/vcmi/swedish.json +++ b/Mods/vcmi/config/vcmi/swedish.json @@ -243,7 +243,7 @@ "vcmi.adventureOptions.showGrid.hover" : "Visa rutnät", "vcmi.adventureOptions.showGrid.help" : "{Visa rutnät}\n\nVisa rutnätsöverlägget som markerar gränserna mellan äventyrskartans brickor/rutor.", "vcmi.adventureOptions.borderScroll.hover" : "Kantrullning", - "vcmi.adventureOptions.borderScroll.help" : "{Kantrullning}\n\nRullar äventyrskartan när markören är till fönsterkanten. Kan inaktiveras genom att hålla ned CTRL-tangenten.", + "vcmi.adventureOptions.borderScroll.help" : "{Kantrullning}\n\nRullar äventyrskartan när markören är angränsande till fönsterkanten. Kan inaktiveras genom att hålla ned CTRL-tangenten.", "vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Hantera armén i nedre högra hörnet", "vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Varelsehantering i infopanelen}\n\nTillåter omarrangering av varelser i infopanelen längst ner till höger på äventyrskartan istället för att bläddra mellan olika infopaneler.", "vcmi.adventureOptions.leftButtonDrag.hover" : "V.klicksdragning", From 7183314413b201a831728e2b099f27d5e0699731 Mon Sep 17 00:00:00 2001 From: Maurycy <55395993+XCOM-HUB@users.noreply.github.com> Date: Mon, 14 Oct 2024 01:30:27 +0200 Subject: [PATCH 29/69] Update swedish.json --- Mods/vcmi/config/vcmi/swedish.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Mods/vcmi/config/vcmi/swedish.json b/Mods/vcmi/config/vcmi/swedish.json index b04096f46..75958bbf5 100644 --- a/Mods/vcmi/config/vcmi/swedish.json +++ b/Mods/vcmi/config/vcmi/swedish.json @@ -378,7 +378,7 @@ "vcmi.randomMapTab.widgets.roadTypesLabel" : "Vägtyper", "vcmi.optionsTab.turnOptions.hover" : "Turomgångsalternativ", - "vcmi.optionsTab.turnOptions.help" : "Ställ in turomgångs-timern och samtidiga turomgångar", + "vcmi.optionsTab.turnOptions.help" : "Turomgångs-timer och samtidiga turomgångar (förinställningar)", "vcmi.optionsTab.chessFieldBase.hover" : "Bas-timern", "vcmi.optionsTab.chessFieldTurn.hover" : "Tur-timern", From b3c5e0680d5b03bddd1fc842a4812226042086fd Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 29 Aug 2024 19:02:21 +0000 Subject: [PATCH 30/69] Install ninja for ios CI builds --- CI/ios/before_install.sh | 2 ++ 1 file changed, 2 insertions(+) diff --git a/CI/ios/before_install.sh b/CI/ios/before_install.sh index a8326e1fd..a90bf89b4 100755 --- a/CI/ios/before_install.sh +++ b/CI/ios/before_install.sh @@ -3,3 +3,5 @@ echo DEVELOPER_DIR=/Applications/Xcode_14.2.app >> $GITHUB_ENV . CI/install_conan_dependencies.sh "dependencies-ios" + +brew install ninja From 1623afd35d23f03c4fa1e11e9ba6c265b8017573 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 29 Aug 2024 19:03:51 +0000 Subject: [PATCH 31/69] Use Ubuntu 24.04 for mingw builds --- .github/workflows/github.yml | 5 +++-- CI/conan/base/cross-macro.j2 | 2 +- CI/mingw-32/before_install.sh | 9 --------- CI/mingw/before_install.sh | 9 --------- 4 files changed, 4 insertions(+), 21 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index fc40fd23a..92ac0352b 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -69,7 +69,7 @@ jobs: extension: exe preset: windows-msvc-release - platform: mingw - os: ubuntu-22.04 + os: ubuntu-24.04 test: 0 pack: 1 pack_type: Release @@ -78,8 +78,9 @@ jobs: cmake_args: -G Ninja preset: windows-mingw-conan-linux conan_profile: mingw64-linux.jinja + conan_prebuilts: dependencies-mingw - platform: mingw-32 - os: ubuntu-22.04 + os: ubuntu-24.04 test: 0 pack: 1 pack_type: Release diff --git a/CI/conan/base/cross-macro.j2 b/CI/conan/base/cross-macro.j2 index 7f4edf0ee..ba3c53212 100644 --- a/CI/conan/base/cross-macro.j2 +++ b/CI/conan/base/cross-macro.j2 @@ -10,7 +10,7 @@ STRIP={{ target_host }}-strip {%- endmacro -%} {% macro generate_env_win32(target_host) -%} -CONAN_SYSTEM_LIBRARY_LOCATION=/usr/lib/gcc/{{ target_host }}/10-posix/ +CONAN_SYSTEM_LIBRARY_LOCATION=/usr/lib/gcc/{{ target_host }}/13-posix/ RC={{ target_host }}-windres {%- endmacro -%} diff --git a/CI/mingw-32/before_install.sh b/CI/mingw-32/before_install.sh index 857f4a716..9305f8b7b 100644 --- a/CI/mingw-32/before_install.sh +++ b/CI/mingw-32/before_install.sh @@ -3,12 +3,3 @@ sudo apt-get update sudo apt-get install ninja-build mingw-w64 nsis sudo update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix - -# Workaround for getting new MinGW headers on Ubuntu 22.04. -# Remove it once MinGW headers version in repository will be 10.0 at least -curl -O -L http://mirrors.kernel.org/ubuntu/pool/universe/m/mingw-w64/mingw-w64-common_10.0.0-3_all.deb \ - && sudo dpkg -i mingw-w64-common_10.0.0-3_all.deb; -curl -O -L http://mirrors.kernel.org/ubuntu/pool/universe/m/mingw-w64/mingw-w64-i686-dev_10.0.0-3_all.deb \ - && sudo dpkg -i mingw-w64-i686-dev_10.0.0-3_all.deb; - -. CI/install_conan_dependencies.sh "dependencies-mingw-32" diff --git a/CI/mingw/before_install.sh b/CI/mingw/before_install.sh index 70fbaf0d5..4ebe8607a 100755 --- a/CI/mingw/before_install.sh +++ b/CI/mingw/before_install.sh @@ -3,12 +3,3 @@ sudo apt-get update sudo apt-get install ninja-build mingw-w64 nsis sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix - -# Workaround for getting new MinGW headers on Ubuntu 22.04. -# Remove it once MinGW headers version in repository will be 10.0 at least -curl -O -L http://mirrors.kernel.org/ubuntu/pool/universe/m/mingw-w64/mingw-w64-common_10.0.0-3_all.deb \ - && sudo dpkg -i mingw-w64-common_10.0.0-3_all.deb; -curl -O -L http://mirrors.kernel.org/ubuntu/pool/universe/m/mingw-w64/mingw-w64-x86-64-dev_10.0.0-3_all.deb \ - && sudo dpkg -i mingw-w64-x86-64-dev_10.0.0-3_all.deb; - -. CI/install_conan_dependencies.sh "dependencies-mingw" From 4dc521743cee9ec4804c5ca9fdaa6a86513077ac Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 29 Aug 2024 19:04:41 +0000 Subject: [PATCH 32/69] Install dependencies as separate CI step --- .github/workflows/github.yml | 15 +++++++++++++-- CI/android/before_install.sh | 4 +--- CI/ios/before_install.sh | 2 -- CI/mac-arm/before_install.sh | 1 - CI/mac-intel/before_install.sh | 1 - CI/mac/before_install.sh | 2 -- 6 files changed, 14 insertions(+), 11 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 92ac0352b..6a6d3d993 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -40,6 +40,7 @@ jobs: extension: dmg preset: macos-conan-ninja-release conan_profile: macos-intel + conan_prebuilts: dependencies-mac-intel conan_options: --options with_apple_system_libs=True artifact_platform: intel - platform: mac-arm @@ -50,6 +51,7 @@ jobs: extension: dmg preset: macos-arm-conan-ninja-release conan_profile: macos-arm + conan_prebuilts: dependencies-mac-arm conan_options: --options with_apple_system_libs=True artifact_platform: arm - platform: ios @@ -60,6 +62,7 @@ jobs: extension: ipa preset: ios-release-conan-ccache conan_profile: ios-arm64 + conan_prebuilts: dependencies-ios conan_options: --options with_apple_system_libs=True - platform: msvc os: windows-latest @@ -89,11 +92,13 @@ jobs: cmake_args: -G Ninja preset: windows-mingw-conan-linux conan_profile: mingw32-linux.jinja + conan_prebuilts: dependencies-mingw-32 - platform: android-32 os: macos-14 extension: apk preset: android-conan-ninja-release conan_profile: android-32 + conan_prebuilts: dependencies-android-32 conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT artifact_platform: armeabi-v7a - platform: android-64 @@ -101,6 +106,7 @@ jobs: extension: apk preset: android-conan-ninja-release conan_profile: android-64 + conan_prebuilts: dependencies-android-64 conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT artifact_platform: arm64-v8a runs-on: ${{ matrix.os }} @@ -109,15 +115,20 @@ jobs: shell: bash steps: - - uses: actions/checkout@v4 + - name: Checkout repository + uses: actions/checkout@v4 with: submodules: recursive - - name: Dependencies + - name: Prepare CI run: source '${{github.workspace}}/CI/${{matrix.platform}}/before_install.sh' env: VCMI_BUILD_PLATFORM: x64 + - name: Install Conan Dependencies + if: "${{ matrix.conan_prebuilts != '' }}" + run: source '${{github.workspace}}/CI/install_conan_dependencies.sh' '${{matrix.conan_prebuilts}}' + # ensure the ccache for each PR is separate so they don't interfere with each other # fall back to ccache of the vcmi/vcmi repo if no PR-specific ccache is found - name: ccache for PRs diff --git a/CI/android/before_install.sh b/CI/android/before_install.sh index 146d52110..fe416b26f 100755 --- a/CI/android/before_install.sh +++ b/CI/android/before_install.sh @@ -2,6 +2,4 @@ echo "ANDROID_NDK_ROOT=$ANDROID_HOME/ndk/25.2.9519653" >> $GITHUB_ENV -brew install ninja - -. CI/install_conan_dependencies.sh "$DEPS_FILENAME" \ No newline at end of file +brew install ninja \ No newline at end of file diff --git a/CI/ios/before_install.sh b/CI/ios/before_install.sh index a90bf89b4..0664cc910 100755 --- a/CI/ios/before_install.sh +++ b/CI/ios/before_install.sh @@ -2,6 +2,4 @@ echo DEVELOPER_DIR=/Applications/Xcode_14.2.app >> $GITHUB_ENV -. CI/install_conan_dependencies.sh "dependencies-ios" - brew install ninja diff --git a/CI/mac-arm/before_install.sh b/CI/mac-arm/before_install.sh index 41701758b..be9945c20 100755 --- a/CI/mac-arm/before_install.sh +++ b/CI/mac-arm/before_install.sh @@ -1,4 +1,3 @@ #!/usr/bin/env bash -DEPS_FILENAME=dependencies-mac-arm . CI/mac/before_install.sh diff --git a/CI/mac-intel/before_install.sh b/CI/mac-intel/before_install.sh index a96955b20..be9945c20 100755 --- a/CI/mac-intel/before_install.sh +++ b/CI/mac-intel/before_install.sh @@ -1,4 +1,3 @@ #!/usr/bin/env bash -DEPS_FILENAME=dependencies-mac-intel . CI/mac/before_install.sh diff --git a/CI/mac/before_install.sh b/CI/mac/before_install.sh index ed11e87df..0664cc910 100755 --- a/CI/mac/before_install.sh +++ b/CI/mac/before_install.sh @@ -3,5 +3,3 @@ echo DEVELOPER_DIR=/Applications/Xcode_14.2.app >> $GITHUB_ENV brew install ninja - -. CI/install_conan_dependencies.sh "$DEPS_FILENAME" From 0e1d5274babcd46ea89cbbe1a97ed5889759205c Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 29 Aug 2024 19:04:58 +0000 Subject: [PATCH 33/69] Generate aab's only for builds on master branch --- .github/workflows/github.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 6a6d3d993..e689e0dc2 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -282,7 +282,7 @@ jobs: echo "ANDROID_AAB_PATH=$ANDROID_AAB_PATH" >> $GITHUB_ENV - name: Android apk artifacts - if: ${{ startsWith(matrix.platform, 'android') }} + if: ${{ startsWith(matrix.platform, 'android') }} uses: actions/upload-artifact@v4 with: name: ${{ env.VCMI_PACKAGE_FILE_NAME }} - ${{ matrix.platform }} @@ -290,7 +290,7 @@ jobs: ${{ env.ANDROID_APK_PATH }} - name: Android aab artifacts - if: ${{ startsWith(matrix.platform, 'android') }} + if: ${{ startsWith(matrix.platform, 'android') && github.ref == 'refs/heads/master' }} uses: actions/upload-artifact@v4 with: name: ${{ env.VCMI_PACKAGE_FILE_NAME }} - ${{ matrix.platform }} - aab From a64f1f1232bceae9e89b106eaf97c79e9665e68b Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 29 Aug 2024 19:05:15 +0000 Subject: [PATCH 34/69] Use newer SDL libraries --- conanfile.py | 53 +++++++++++++++++++++++++++++++++++++++++----------- 1 file changed, 42 insertions(+), 11 deletions(-) diff --git a/conanfile.py b/conanfile.py index c9c5df23d..891eb2a89 100644 --- a/conanfile.py +++ b/conanfile.py @@ -15,10 +15,11 @@ class VCMI(ConanFile): "minizip/[~1.2.12]", ] _clientRequires = [ - "sdl/[~2.26.1 || >=2.0.20 <=2.22.0]", # versions in between have broken sound - "sdl_image/[~2.0.5]", - "sdl_mixer/[~2.0.4]", - "sdl_ttf/[~2.0.18]", + # Versions between 2.5-2.8 have broken loading of palette sdl images which a lot of mods use + # there is workaround that require disabling cmake flag which is not available in conan recipes. + # Bug is fixed in version 2.8, however it is not available in conan at the moment + "sdl_image/2.0.5", + "sdl_ttf/[>=2.0.18]", "onetbb/[^2021.7 <2021.10]", # 2021.10+ breaks mobile builds due to added hwloc dependency "xz_utils/[>=5.2.5]", # Required for innoextract ] @@ -52,15 +53,36 @@ class VCMI(ConanFile): # static Qt for iOS is the only viable option at the moment self.options["qt"].shared = self.settings.os != "iOS" - if self.settings.os == "Android": - self.options["qt"].android_sdk = tools.get_env("ANDROID_HOME", default="") - # TODO: enable for all platforms if self.settings.os == "Android": self.options["bzip2"].shared = True self.options["libiconv"].shared = True self.options["zlib"].shared = True + # TODO: enable for all platforms? + if self.settings.os == "Windows": + self.options["sdl"].shared = True + self.options["sdl_image"].shared = True + self.options["sdl_mixer"].shared = True + self.options["sdl_ttf"].shared = True + + if self.settings.os == "iOS": + # TODO: ios - newer sdl fails to link + self.requires("sdl/2.26.1") + self.requires("sdl_mixer/2.0.4") + elif self.settings.os == "Android": + # On Android SDL version must be same as version of Java wrapper for SDL in VCMI source code + self.requires("sdl/2.26.5") + self.requires("sdl_mixer/2.0.4") + else: + # upcoming SDL version 3.0+ is not supported at the moment due to API breakage + # SDL versions between 2.22-2.26.1 have broken sound + self.requires("sdl/[^2.26 || >=2.0.20 <=2.22.0]") + self.requires("sdl_mixer/[>=2.0.4]") + + if self.settings.os == "Android": + self.options["qt"].android_sdk = tools.get_env("ANDROID_HOME", default="") + if self.options.default_options_of_requirements: return @@ -149,8 +171,13 @@ class VCMI(ConanFile): self.options["sdl"].sdl2main = self.settings.os != "iOS" self.options["sdl"].vulkan = False + # bmp, png are the only ones that needs to be supported + # pcx is also enabled since some people might use it due to H3 using format named 'pcx' (but unrelated to sdl_image pcx) + # dds support may be useful for HD edition, but not supported by sdl_image at the moment + self.options["sdl_image"].gif = False self.options["sdl_image"].lbm = False self.options["sdl_image"].pnm = False + self.options["sdl_image"].qoi = False self.options["sdl_image"].svg = False self.options["sdl_image"].tga = False self.options["sdl_image"].with_libjpeg = False @@ -162,13 +189,17 @@ class VCMI(ConanFile): if is_apple_os(self): self.options["sdl_image"].imageio = True + # mp3, ogg and wav are the only ones that needs to be supported + # opus is nice to have, but fails to build in CI + # flac can be considered, but generally unnecessary self.options["sdl_mixer"].flac = False - self.options["sdl_mixer"].mad = False - self.options["sdl_mixer"].mikmod = False self.options["sdl_mixer"].modplug = False - self.options["sdl_mixer"].nativemidi = False self.options["sdl_mixer"].opus = False - self.options["sdl_mixer"].wav = False + if self.settings.os == "iOS" or self.settings.os == "Android": + # only available in older sdl_mixer version, removed in newer version + self.options["sdl_mixer"].mad = False + self.options["sdl_mixer"].mikmod = False + self.options["sdl_mixer"].nativemidi = False def _disableQtOptions(disableFlag, options): return " ".join([f"-{disableFlag}-{tool}" for tool in options]) From 289ed742d090fdcd0adeb03137d0b4853237ecc6 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 29 Aug 2024 21:28:55 +0000 Subject: [PATCH 35/69] Disable unused boost_url --- conanfile.py | 1 + 1 file changed, 1 insertion(+) diff --git a/conanfile.py b/conanfile.py index 891eb2a89..ab824158e 100644 --- a/conanfile.py +++ b/conanfile.py @@ -108,6 +108,7 @@ class VCMI(ConanFile): self.options["boost"].without_timer = True self.options["boost"].without_type_erasure = True self.options["boost"].without_wave = True + self.options["boost"].without_url = True self.options["ffmpeg"].disable_all_bitstream_filters = True self.options["ffmpeg"].disable_all_decoders = True From ecf063cd1c86a7a34b2a28d803de96e2cb83c74b Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 6 Sep 2024 16:54:49 +0000 Subject: [PATCH 36/69] Reorganized layout of CI directory, move all before_install files into common directory, remove copy-pasted files --- .github/workflows/github.yml | 12 +++++++++++- CI/android-32/before_install.sh | 4 ---- CI/android-64/before_install.sh | 4 ---- CI/android/before_install.sh | 5 ----- CI/before_install/android.sh | 4 ++++ .../linux_qt5.sh} | 5 ++--- .../linux_qt6.sh} | 4 +++- .../before_install.sh => before_install/macos.sh} | 0 .../mingw_x86.sh} | 0 .../mingw_x86_64.sh} | 0 .../before_install.sh => before_install/msvc.sh} | 0 CI/linux-qt6/upload_package.sh | 1 - CI/linux/upload_package.sh | 1 - CI/mac-arm/before_install.sh | 3 --- CI/mac-intel/before_install.sh | 3 --- CI/mac/before_install.sh | 5 ----- CI/{linux-qt6 => }/validate_json.py | 0 17 files changed, 20 insertions(+), 31 deletions(-) delete mode 100755 CI/android-32/before_install.sh delete mode 100755 CI/android-64/before_install.sh delete mode 100755 CI/android/before_install.sh create mode 100644 CI/before_install/android.sh rename CI/{linux/before_install.sh => before_install/linux_qt5.sh} (80%) rename CI/{linux-qt6/before_install.sh => before_install/linux_qt6.sh} (76%) rename CI/{ios/before_install.sh => before_install/macos.sh} (100%) mode change 100755 => 100644 rename CI/{mingw-32/before_install.sh => before_install/mingw_x86.sh} (100%) rename CI/{mingw/before_install.sh => before_install/mingw_x86_64.sh} (100%) rename CI/{msvc/before_install.sh => before_install/msvc.sh} (100%) delete mode 100644 CI/linux-qt6/upload_package.sh delete mode 100644 CI/linux/upload_package.sh delete mode 100755 CI/mac-arm/before_install.sh delete mode 100755 CI/mac-intel/before_install.sh delete mode 100755 CI/mac/before_install.sh rename CI/{linux-qt6 => }/validate_json.py (100%) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index e689e0dc2..4a4acb2ad 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -23,14 +23,17 @@ jobs: - platform: linux-qt6 os: ubuntu-24.04 test: 0 + before_install: linux_qt6.sh preset: linux-clang-test - platform: linux os: ubuntu-24.04 test: 1 + before_install: linux_qt5.sh preset: linux-gcc-test - platform: linux os: ubuntu-20.04 test: 0 + before_install: linux_qt5.sh preset: linux-gcc-debug - platform: mac-intel os: macos-13 @@ -38,6 +41,7 @@ jobs: pack: 1 pack_type: Release extension: dmg + before_install: macos.sh preset: macos-conan-ninja-release conan_profile: macos-intel conan_prebuilts: dependencies-mac-intel @@ -49,6 +53,7 @@ jobs: pack: 1 pack_type: Release extension: dmg + before_install: macos.sh preset: macos-arm-conan-ninja-release conan_profile: macos-arm conan_prebuilts: dependencies-mac-arm @@ -60,6 +65,7 @@ jobs: pack: 1 pack_type: Release extension: ipa + before_install: macos.sh preset: ios-release-conan-ccache conan_profile: ios-arm64 conan_prebuilts: dependencies-ios @@ -70,6 +76,7 @@ jobs: pack: 1 pack_type: RelWithDebInfo extension: exe + before_install: msvc.sh preset: windows-msvc-release - platform: mingw os: ubuntu-24.04 @@ -79,6 +86,7 @@ jobs: extension: exe cpack_args: -D CPACK_NSIS_EXECUTABLE=`which makensis` cmake_args: -G Ninja + before_install: mingw_x86_64.sh preset: windows-mingw-conan-linux conan_profile: mingw64-linux.jinja conan_prebuilts: dependencies-mingw @@ -90,6 +98,7 @@ jobs: extension: exe cpack_args: -D CPACK_NSIS_EXECUTABLE=`which makensis` cmake_args: -G Ninja + before_install: mingw_x86.sh preset: windows-mingw-conan-linux conan_profile: mingw32-linux.jinja conan_prebuilts: dependencies-mingw-32 @@ -121,7 +130,8 @@ jobs: submodules: recursive - name: Prepare CI - run: source '${{github.workspace}}/CI/${{matrix.platform}}/before_install.sh' + if: "${{ matrix.before_install != '' }}" + run: source '${{github.workspace}}/CI/before_install/${{matrix.before_install}}' env: VCMI_BUILD_PLATFORM: x64 diff --git a/CI/android-32/before_install.sh b/CI/android-32/before_install.sh deleted file mode 100755 index 67cacaddf..000000000 --- a/CI/android-32/before_install.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -DEPS_FILENAME=dependencies-android-32 -. CI/android/before_install.sh diff --git a/CI/android-64/before_install.sh b/CI/android-64/before_install.sh deleted file mode 100755 index af0a36874..000000000 --- a/CI/android-64/before_install.sh +++ /dev/null @@ -1,4 +0,0 @@ -#!/usr/bin/env bash - -DEPS_FILENAME=dependencies-android-64 -. CI/android/before_install.sh diff --git a/CI/android/before_install.sh b/CI/android/before_install.sh deleted file mode 100755 index fe416b26f..000000000 --- a/CI/android/before_install.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -echo "ANDROID_NDK_ROOT=$ANDROID_HOME/ndk/25.2.9519653" >> $GITHUB_ENV - -brew install ninja \ No newline at end of file diff --git a/CI/before_install/android.sh b/CI/before_install/android.sh new file mode 100644 index 000000000..9fba7de9f --- /dev/null +++ b/CI/before_install/android.sh @@ -0,0 +1,4 @@ +#!/bin/sh + +sudo apt-get update +sudo apt-get install ninja-build diff --git a/CI/linux/before_install.sh b/CI/before_install/linux_qt5.sh similarity index 80% rename from CI/linux/before_install.sh rename to CI/before_install/linux_qt5.sh index 5df49a521..ebf9faeb1 100644 --- a/CI/linux/before_install.sh +++ b/CI/before_install/linux_qt5.sh @@ -1,6 +1,5 @@ #!/bin/sh -sudo apt remove needrestart sudo apt-get update # Dependencies @@ -9,6 +8,6 @@ sudo apt-get update # - debian build settings at debian/control sudo apt-get install libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev libboost-iostreams-dev \ libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev \ -qtbase5-dev \ +qtbase5-dev qttools5-dev \ ninja-build zlib1g-dev libavformat-dev libswscale-dev libtbb-dev libluajit-5.1-dev \ -libminizip-dev libfuzzylite-dev qttools5-dev libsqlite3-dev # Optional dependencies +libminizip-dev libfuzzylite-dev libsqlite3-dev # Optional dependencies diff --git a/CI/linux-qt6/before_install.sh b/CI/before_install/linux_qt6.sh similarity index 76% rename from CI/linux-qt6/before_install.sh rename to CI/before_install/linux_qt6.sh index b88d42704..422b50e98 100644 --- a/CI/linux-qt6/before_install.sh +++ b/CI/before_install/linux_qt6.sh @@ -1,9 +1,11 @@ #!/bin/sh -sudo apt remove needrestart sudo apt-get update # Dependencies +# In case of change in dependencies list please also update: +# - developer docs at docs/developer/Building_Linux.md +# - debian build settings at debian/control sudo apt-get install libboost-dev libboost-filesystem-dev libboost-system-dev libboost-thread-dev libboost-program-options-dev libboost-locale-dev libboost-iostreams-dev \ libsdl2-dev libsdl2-image-dev libsdl2-mixer-dev libsdl2-ttf-dev \ qt6-base-dev qt6-base-dev-tools qt6-tools-dev qt6-tools-dev-tools qt6-l10n-tools \ diff --git a/CI/ios/before_install.sh b/CI/before_install/macos.sh old mode 100755 new mode 100644 similarity index 100% rename from CI/ios/before_install.sh rename to CI/before_install/macos.sh diff --git a/CI/mingw-32/before_install.sh b/CI/before_install/mingw_x86.sh similarity index 100% rename from CI/mingw-32/before_install.sh rename to CI/before_install/mingw_x86.sh diff --git a/CI/mingw/before_install.sh b/CI/before_install/mingw_x86_64.sh similarity index 100% rename from CI/mingw/before_install.sh rename to CI/before_install/mingw_x86_64.sh diff --git a/CI/msvc/before_install.sh b/CI/before_install/msvc.sh similarity index 100% rename from CI/msvc/before_install.sh rename to CI/before_install/msvc.sh diff --git a/CI/linux-qt6/upload_package.sh b/CI/linux-qt6/upload_package.sh deleted file mode 100644 index 1a2485251..000000000 --- a/CI/linux-qt6/upload_package.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/sh diff --git a/CI/linux/upload_package.sh b/CI/linux/upload_package.sh deleted file mode 100644 index 1a2485251..000000000 --- a/CI/linux/upload_package.sh +++ /dev/null @@ -1 +0,0 @@ -#!/bin/sh diff --git a/CI/mac-arm/before_install.sh b/CI/mac-arm/before_install.sh deleted file mode 100755 index be9945c20..000000000 --- a/CI/mac-arm/before_install.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -. CI/mac/before_install.sh diff --git a/CI/mac-intel/before_install.sh b/CI/mac-intel/before_install.sh deleted file mode 100755 index be9945c20..000000000 --- a/CI/mac-intel/before_install.sh +++ /dev/null @@ -1,3 +0,0 @@ -#!/usr/bin/env bash - -. CI/mac/before_install.sh diff --git a/CI/mac/before_install.sh b/CI/mac/before_install.sh deleted file mode 100755 index 0664cc910..000000000 --- a/CI/mac/before_install.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -echo DEVELOPER_DIR=/Applications/Xcode_14.2.app >> $GITHUB_ENV - -brew install ninja diff --git a/CI/linux-qt6/validate_json.py b/CI/validate_json.py similarity index 100% rename from CI/linux-qt6/validate_json.py rename to CI/validate_json.py From 2d2bc8293f53f77f013f6f6bdf2ef6d259f71920 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 6 Sep 2024 16:55:35 +0000 Subject: [PATCH 37/69] Delete old coverity files --- CI/msvc/build_script.bat | 6 ------ CI/msvc/coverity_build_script.bat | 5 ----- CI/msvc/coverity_upload_script.ps | 17 ----------------- 3 files changed, 28 deletions(-) delete mode 100644 CI/msvc/build_script.bat delete mode 100644 CI/msvc/coverity_build_script.bat delete mode 100644 CI/msvc/coverity_upload_script.ps diff --git a/CI/msvc/build_script.bat b/CI/msvc/build_script.bat deleted file mode 100644 index 5bd1d8485..000000000 --- a/CI/msvc/build_script.bat +++ /dev/null @@ -1,6 +0,0 @@ -cd %APPVEYOR_BUILD_FOLDER% -cd build_%VCMI_BUILD_PLATFORM% - -cmake --build . --config %VCMI_BUILD_CONFIGURATION% -- /maxcpucount:2 - -cpack diff --git a/CI/msvc/coverity_build_script.bat b/CI/msvc/coverity_build_script.bat deleted file mode 100644 index 9fe2cbf2a..000000000 --- a/CI/msvc/coverity_build_script.bat +++ /dev/null @@ -1,5 +0,0 @@ -cd %APPVEYOR_BUILD_FOLDER% -cd build_%VCMI_BUILD_PLATFORM% - -echo Building with coverity... -cov-build.exe --dir cov-int cmake --build . --config %VCMI_BUILD_CONFIGURATION% -- /maxcpucount:2 diff --git a/CI/msvc/coverity_upload_script.ps b/CI/msvc/coverity_upload_script.ps deleted file mode 100644 index e830ae970..000000000 --- a/CI/msvc/coverity_upload_script.ps +++ /dev/null @@ -1,17 +0,0 @@ -7z a "$Env:APPVEYOR_BUILD_FOLDER\$Env:APPVEYOR_PROJECT_NAME.zip" "$Env:APPVEYOR_BUILD_FOLDER\build_$Env:VCMI_BUILD_PLATFORM\cov-int\" - -# cf. http://stackoverflow.com/a/25045154/335418 -Remove-item alias:curl - -Write-Host "Uploading Coverity analysis result..." -ForegroundColor "Green" - -curl --silent --show-error ` - --output curl-out.txt ` - --form token="$Env:coverity_token" ` - --form email="$Env:coverity_email" ` - --form "file=@$Env:APPVEYOR_BUILD_FOLDER\$Env:APPVEYOR_PROJECT_NAME.zip" ` - --form version="$Env:APPVEYOR_REPO_COMMIT" ` - --form description="CI server scheduled build." ` - https://scan.coverity.com/builds?project=vcmi%2Fvcmi - -cat .\curl-out.txt From 501622229df8ab18f1e9ab2ccaf07d0aebfd8201 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 6 Sep 2024 16:57:37 +0000 Subject: [PATCH 38/69] Use new prebuilts package --- .github/workflows/github.yml | 26 ++++++++++++-------------- CI/install_conan_dependencies.sh | 2 +- CMakeLists.txt | 20 ++++++++++++-------- conanfile.py | 8 +++----- 4 files changed, 28 insertions(+), 28 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 4a4acb2ad..361e650c0 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -78,45 +78,43 @@ jobs: extension: exe before_install: msvc.sh preset: windows-msvc-release - - platform: mingw + - platform: mingw_x86_64 os: ubuntu-24.04 test: 0 pack: 1 pack_type: Release extension: exe - cpack_args: -D CPACK_NSIS_EXECUTABLE=`which makensis` cmake_args: -G Ninja before_install: mingw_x86_64.sh preset: windows-mingw-conan-linux conan_profile: mingw64-linux.jinja - conan_prebuilts: dependencies-mingw - - platform: mingw-32 + conan_prebuilts: dependencies-mingw-x86-64 + - platform: mingw_x86 os: ubuntu-24.04 test: 0 pack: 1 pack_type: Release extension: exe - cpack_args: -D CPACK_NSIS_EXECUTABLE=`which makensis` cmake_args: -G Ninja before_install: mingw_x86.sh preset: windows-mingw-conan-linux conan_profile: mingw32-linux.jinja - conan_prebuilts: dependencies-mingw-32 + conan_prebuilts: dependencies-mingw-x86 - platform: android-32 - os: macos-14 + os: ubuntu-24.04 extension: apk preset: android-conan-ninja-release - conan_profile: android-32 - conan_prebuilts: dependencies-android-32 - conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT + before_install: android.sh + conan_profile: android-32-ndk + conan_prebuilts: dependencies-android-armeabi-v7a artifact_platform: armeabi-v7a - platform: android-64 - os: macos-14 + os: ubuntu-24.04 extension: apk preset: android-conan-ninja-release - conan_profile: android-64 - conan_prebuilts: dependencies-android-64 - conan_options: --conf tools.android:ndk_path=$ANDROID_NDK_ROOT + before_install: android.sh + conan_profile: android-64-ndk + conan_prebuilts: dependencies-android-arm64-v8a artifact_platform: arm64-v8a runs-on: ${{ matrix.os }} defaults: diff --git a/CI/install_conan_dependencies.sh b/CI/install_conan_dependencies.sh index 2b14811d0..593f96e30 100644 --- a/CI/install_conan_dependencies.sh +++ b/CI/install_conan_dependencies.sh @@ -1,6 +1,6 @@ #!/usr/bin/env bash -RELEASE_TAG="1.2" +RELEASE_TAG="1.3" FILENAME="$1" DOWNLOAD_URL="https://github.com/vcmi/vcmi-dependencies/releases/download/$RELEASE_TAG/$FILENAME.txz" diff --git a/CMakeLists.txt b/CMakeLists.txt index 10c0ca817..e7e02f550 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -180,11 +180,6 @@ else() add_definitions(-DVCMI_NO_EXTRA_VERSION) endif(ENABLE_GITVERSION) -# Precompiled header configuration -if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU" AND CMAKE_CXX_COMPILER_VERSION VERSION_LESS 6.0 ) - set(ENABLE_PCH OFF) # broken -endif() - if(ENABLE_PCH) macro(enable_pch name) target_precompile_headers(${name} PRIVATE $<$:>) @@ -328,7 +323,6 @@ if(MINGW OR MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4244") # 4244: conversion from 'xxx' to 'yyy', possible loss of data set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4267") # 4267: conversion from 'xxx' to 'yyy', possible loss of data set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4275") # 4275: non dll-interface class 'xxx' used as base for dll-interface class - #set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /wd4800") # 4800: implicit conversion from 'xxx' to bool. Possible information loss if(ENABLE_STRICT_COMPILATION) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX") # Treats all compiler warnings as errors @@ -493,14 +487,23 @@ if (ENABLE_CLIENT) if(TARGET SDL2_image::SDL2_image) add_library(SDL2::Image ALIAS SDL2_image::SDL2_image) endif() + if(TARGET SDL2_image::SDL2_image-static) + add_library(SDL2::Image ALIAS SDL2_image::SDL2_image-static) + endif() find_package(SDL2_mixer REQUIRED) if(TARGET SDL2_mixer::SDL2_mixer) add_library(SDL2::Mixer ALIAS SDL2_mixer::SDL2_mixer) endif() + if(TARGET SDL2_mixer::SDL2_mixer-static) + add_library(SDL2::Mixer ALIAS SDL2_mixer::SDL2_mixer-static) + endif() find_package(SDL2_ttf REQUIRED) if(TARGET SDL2_ttf::SDL2_ttf) add_library(SDL2::TTF ALIAS SDL2_ttf::SDL2_ttf) endif() + if(TARGET SDL2_ttf::SDL2_ttf-static) + add_library(SDL2::TTF ALIAS SDL2_ttf::SDL2_ttf-static) + endif() endif() if(ENABLE_LOBBY) @@ -727,7 +730,7 @@ endif() if(WIN32) if(TBB_FOUND AND MSVC) - install_vcpkg_imported_tgt(TBB::tbb) + install_vcpkg_imported_tgt(TBB::tbb) endif() if(USING_CONAN) @@ -737,7 +740,8 @@ if(WIN32) ${dep_files} "${CMAKE_SYSROOT}/bin/*.dll" "${CMAKE_SYSROOT}/lib/*.dll" - "${CONAN_SYSTEM_LIBRARY_LOCATION}/*.dll") + "${CONAN_SYSTEM_LIBRARY_LOCATION}/libgcc_s_seh-1.dll" + "${CONAN_SYSTEM_LIBRARY_LOCATION}/libstdc++-6.dll") else() file(GLOB dep_files ${dep_files} diff --git a/conanfile.py b/conanfile.py index ab824158e..08621c6ef 100644 --- a/conanfile.py +++ b/conanfile.py @@ -47,9 +47,7 @@ class VCMI(ConanFile): self.options["freetype"].shared = self.settings.os == "Android" # SDL_image and Qt depend on it, in iOS both are static - # Enable static libpng due to https://github.com/conan-io/conan-center-index/issues/15440, - # which leads to VCMI crashes of MinGW - self.options["libpng"].shared = not (self.settings.os == "Windows" and cross_building(self)) and self.settings.os != "iOS" + self.options["libpng"].shared = not self.settings.os != "iOS" # static Qt for iOS is the only viable option at the moment self.options["qt"].shared = self.settings.os != "iOS" @@ -173,12 +171,12 @@ class VCMI(ConanFile): self.options["sdl"].vulkan = False # bmp, png are the only ones that needs to be supported - # pcx is also enabled since some people might use it due to H3 using format named 'pcx' (but unrelated to sdl_image pcx) # dds support may be useful for HD edition, but not supported by sdl_image at the moment self.options["sdl_image"].gif = False self.options["sdl_image"].lbm = False self.options["sdl_image"].pnm = False - self.options["sdl_image"].qoi = False + self.options["sdl_image"].pcx = False + #self.options["sdl_image"].qoi = False # sdl_image >=2.6 self.options["sdl_image"].svg = False self.options["sdl_image"].tga = False self.options["sdl_image"].with_libjpeg = False From 06cd74dde6f00f76bc9912ec2441cf6b8a29b5fc Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 6 Sep 2024 16:59:54 +0000 Subject: [PATCH 39/69] Use new path to the script --- .github/workflows/github.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 361e650c0..c7a7f1116 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -379,4 +379,4 @@ jobs: - name: Validate JSON run: | sudo apt install python3-jstyleson - python3 CI/linux-qt6/validate_json.py + python3 CI/validate_json.py From 9a1f26883de33ac2e217b00cbff660bd0e59e554 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 6 Sep 2024 17:00:04 +0000 Subject: [PATCH 40/69] Update documentation --- docs/modders/File_Formats.md | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) diff --git a/docs/modders/File_Formats.md b/docs/modders/File_Formats.md index d1466e4cf..b80188625 100644 --- a/docs/modders/File_Formats.md +++ b/docs/modders/File_Formats.md @@ -25,13 +25,21 @@ For animations VCMI supports .def format from Heroes III as well as alternative ### Sounds -For sounds VCMI currently requires .wav format. Generally, VCMI will support any .wav parameters, however you might want to use high-bitrate versions, such as 44100 Hz or 48000 Hz, 32 bit, 1 or 2 channels +For sounds VCMI currently supports: +- .ogg/vorbis format - preferred for mods. Unlike wav, vorbis uses compression which may cause some data loss, however even 128kbit is generally undistinguishable from lossless formats +- .wav format. This is format used by H3. It is supported by vcmi, but it may result in large file sizes (and as result - large mods) -Support for additional formats, such as ogg/vorbis and ogg/opus is likely to be added in future +Generally, VCMI will support any audio parameters, however you might want to use high-bitrate versions, such as 44100 Hz or 48000 Hz, 32 bit, 1 or 2 channels + +Support for additional formats, such as ogg/opus or flac may be added in future ### Music -For sounds VCMI currently requires .mp3 format. Support for additional formats, such as ogg/vorbis and ogg/opus is likely to be added in future +For music VCMI currently supports: +- .ogg/vorbis format - preferred for mods. Generally offers better quality and lower sizes compared to mp3 +- .mp3 format. This is format used by H3 + +Support for additional formats, such as ogg/opus may be added in future ### Video From 2506490db4b1f4d210118988ce1026ce4fcc25e2 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 9 Sep 2024 20:19:18 +0000 Subject: [PATCH 41/69] Use python provided in CI runner image instead of installing via action --- .github/workflows/github.yml | 13 +++---------- 1 file changed, 3 insertions(+), 10 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index c7a7f1116..5c8785a00 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -178,15 +178,13 @@ jobs: mkdir -p ~/.local/share/vcmi/ mv h3_assets/* ~/.local/share/vcmi/ - - uses: actions/setup-python@v5 + - name: Install Conan if: "${{ matrix.conan_profile != '' }}" - with: - python-version: '3.10' + run: pipx install 'conan<2.0' - - name: Conan setup + - name: Install Conan profile if: "${{ matrix.conan_profile != '' }}" run: | - pip3 install 'conan<2.0' conan profile new default --detect conan install . \ --install-folder=conan-generated \ @@ -364,11 +362,6 @@ jobs: 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 \ From a63d3a11c48e5dd680067b02ec0d6e2bd71da2ce Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Fri, 6 Sep 2024 16:59:31 +0000 Subject: [PATCH 42/69] Simplify cpack logic --- .github/workflows/github.yml | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 5c8785a00..e737f47fb 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -261,11 +261,13 @@ jobs: if: ${{ matrix.pack == 1 }} run: | cd '${{github.workspace}}/out/build/${{matrix.preset}}' - CPACK_PATH=`which -a cpack | grep -m1 -v -i chocolatey` - counter=0; until "$CPACK_PATH" -C ${{matrix.pack_type}} ${{ matrix.cpack_args }} || ((counter > 20)); do sleep 3; ((counter++)); done - test -f '${{github.workspace}}/CI/${{matrix.platform}}/post_pack.sh' \ - && '${{github.workspace}}/CI/${{matrix.platform}}/post_pack.sh' '${{github.workspace}}' "$(ls '${{ env.VCMI_PACKAGE_FILE_NAME }}'.*)" - rm -rf _CPack_Packages + + # Workaround for CPack bug on macOS 13 + counter=0 + until cpack -C ${{matrix.pack_type}} || ((counter > 20)) + do sleep 3 + ((counter++)) + done - name: Artifacts if: ${{ matrix.pack == 1 }} From eb06eb15cd31e354e05680f9f1cbeba894b5e929 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 9 Sep 2024 20:32:44 +0000 Subject: [PATCH 43/69] Clean up workflow --- .github/workflows/github.yml | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index e737f47fb..768885299 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -261,7 +261,7 @@ jobs: if: ${{ matrix.pack == 1 }} run: | cd '${{github.workspace}}/out/build/${{matrix.preset}}' - + # Workaround for CPack bug on macOS 13 counter=0 until cpack -C ${{matrix.pack_type}} || ((counter > 20)) @@ -289,15 +289,15 @@ jobs: echo "ANDROID_APK_PATH=$ANDROID_APK_PATH" >> $GITHUB_ENV echo "ANDROID_AAB_PATH=$ANDROID_AAB_PATH" >> $GITHUB_ENV - - name: Android apk artifacts - if: ${{ startsWith(matrix.platform, 'android') }} + - name: Upload android apk artifacts + if: ${{ startsWith(matrix.platform, 'android') }} uses: actions/upload-artifact@v4 with: name: ${{ env.VCMI_PACKAGE_FILE_NAME }} - ${{ matrix.platform }} path: | ${{ env.ANDROID_APK_PATH }} - - name: Android aab artifacts + - name: Upload Android aab artifacts if: ${{ startsWith(matrix.platform, 'android') && github.ref == 'refs/heads/master' }} uses: actions/upload-artifact@v4 with: @@ -305,7 +305,7 @@ jobs: path: | ${{ env.ANDROID_AAB_PATH }} - - name: Symbols + - name: Upload debug symbols if: ${{ matrix.platform == 'msvc' }} uses: actions/upload-artifact@v4 with: From 6b1fd428bd016f221ca22f2500134a6fbe4a983f Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 19 Sep 2024 17:04:40 +0000 Subject: [PATCH 44/69] Use shared setup file for 32 and 64 bit bingw --- .github/workflows/github.yml | 4 ++-- CI/before_install/{mingw_x86.sh => mingw.sh} | 2 ++ CI/before_install/mingw_x86_64.sh | 5 ----- 3 files changed, 4 insertions(+), 7 deletions(-) rename CI/before_install/{mingw_x86.sh => mingw.sh} (65%) delete mode 100755 CI/before_install/mingw_x86_64.sh diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 768885299..fdbc9b159 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -85,7 +85,7 @@ jobs: pack_type: Release extension: exe cmake_args: -G Ninja - before_install: mingw_x86_64.sh + before_install: mingw.sh preset: windows-mingw-conan-linux conan_profile: mingw64-linux.jinja conan_prebuilts: dependencies-mingw-x86-64 @@ -96,7 +96,7 @@ jobs: pack_type: Release extension: exe cmake_args: -G Ninja - before_install: mingw_x86.sh + before_install: mingw.sh preset: windows-mingw-conan-linux conan_profile: mingw32-linux.jinja conan_prebuilts: dependencies-mingw-x86 diff --git a/CI/before_install/mingw_x86.sh b/CI/before_install/mingw.sh similarity index 65% rename from CI/before_install/mingw_x86.sh rename to CI/before_install/mingw.sh index 9305f8b7b..2d01d179e 100644 --- a/CI/before_install/mingw_x86.sh +++ b/CI/before_install/mingw.sh @@ -2,4 +2,6 @@ sudo apt-get update sudo apt-get install ninja-build mingw-w64 nsis + sudo update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix +sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix \ No newline at end of file diff --git a/CI/before_install/mingw_x86_64.sh b/CI/before_install/mingw_x86_64.sh deleted file mode 100755 index 4ebe8607a..000000000 --- a/CI/before_install/mingw_x86_64.sh +++ /dev/null @@ -1,5 +0,0 @@ -#!/usr/bin/env bash - -sudo apt-get update -sudo apt-get install ninja-build mingw-w64 nsis -sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix From ab2c5ba64fc521b31049e5c739a13778a74339aa Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 19 Sep 2024 17:56:12 +0000 Subject: [PATCH 45/69] Add workaround for Android NDK installed via conan - required for correct stripping of resulting binaries --- .github/workflows/github.yml | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index fdbc9b159..e5ce1fd74 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -196,7 +196,13 @@ jobs: env: GENERATE_ONLY_BUILT_CONFIG: 1 - - uses: actions/setup-java@v4 + # Workaround for gradle not discovering SDK that was installed via conan + - name: Find Android NDK + if: ${{ startsWith(matrix.platform, 'android') }} + run: sudo ln -s -T /home/runner/.conan/data/android-ndk/r25c/_/_/package/4db1be536558d833e52e862fd84d64d75c2b3656/bin /usr/local/lib/android/sdk/ndk/25.2.9519653 + + - name: Install Java + uses: actions/setup-java@v4 if: ${{ startsWith(matrix.platform, 'android') }} with: distribution: 'temurin' From 55916fad0a675ff7f92407da81db1266bd4692ba Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 19 Sep 2024 17:57:27 +0000 Subject: [PATCH 46/69] Fix libpng linkage - shared on all platforms other than iOS --- conanfile.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conanfile.py b/conanfile.py index 08621c6ef..6e3ac8a35 100644 --- a/conanfile.py +++ b/conanfile.py @@ -47,7 +47,7 @@ class VCMI(ConanFile): self.options["freetype"].shared = self.settings.os == "Android" # SDL_image and Qt depend on it, in iOS both are static - self.options["libpng"].shared = not self.settings.os != "iOS" + self.options["libpng"].shared = self.settings.os != "iOS" # static Qt for iOS is the only viable option at the moment self.options["qt"].shared = self.settings.os != "iOS" From 34447fd844b558b3c6f7876fa959f2038fafbc85 Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Thu, 19 Sep 2024 17:59:37 +0000 Subject: [PATCH 47/69] Fix missing standard libraries from package on mingw --- CMakeLists.txt | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/CMakeLists.txt b/CMakeLists.txt index e7e02f550..78a4a7027 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -740,7 +740,8 @@ if(WIN32) ${dep_files} "${CMAKE_SYSROOT}/bin/*.dll" "${CMAKE_SYSROOT}/lib/*.dll" - "${CONAN_SYSTEM_LIBRARY_LOCATION}/libgcc_s_seh-1.dll" + "${CONAN_SYSTEM_LIBRARY_LOCATION}/libgcc_s_dw2-1.dll" # for 32-bit only? + "${CONAN_SYSTEM_LIBRARY_LOCATION}/libgcc_s_seh-1.dll" # for 64-bit only? "${CONAN_SYSTEM_LIBRARY_LOCATION}/libstdc++-6.dll") else() file(GLOB dep_files From 55e79b1b966f81a03cae1f97aa42648675ec8a6d Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 14 Oct 2024 13:23:19 +0000 Subject: [PATCH 48/69] Remove Android CI workaround --- .github/workflows/github.yml | 1 - 1 file changed, 1 deletion(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index e5ce1fd74..6d93ca4ad 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -17,7 +17,6 @@ env: jobs: build: strategy: - fail-fast: false matrix: include: - platform: linux-qt6 From ccd0edf13d5e9ff0cb0227eaa0c467d93f617bea Mon Sep 17 00:00:00 2001 From: Ivan Savenko Date: Mon, 14 Oct 2024 13:23:48 +0000 Subject: [PATCH 49/69] Changes according to review --- .github/workflows/github.yml | 4 ++-- CI/before_install/mingw.sh | 2 +- conanfile.py | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/.github/workflows/github.yml b/.github/workflows/github.yml index 6d93ca4ad..1fec92b84 100644 --- a/.github/workflows/github.yml +++ b/.github/workflows/github.yml @@ -269,8 +269,8 @@ jobs: # Workaround for CPack bug on macOS 13 counter=0 - until cpack -C ${{matrix.pack_type}} || ((counter > 20)) - do sleep 3 + until cpack -C ${{matrix.pack_type}} || ((counter > 20)); do + sleep 3 ((counter++)) done diff --git a/CI/before_install/mingw.sh b/CI/before_install/mingw.sh index 2d01d179e..30a865d49 100644 --- a/CI/before_install/mingw.sh +++ b/CI/before_install/mingw.sh @@ -4,4 +4,4 @@ sudo apt-get update sudo apt-get install ninja-build mingw-w64 nsis sudo update-alternatives --set i686-w64-mingw32-g++ /usr/bin/i686-w64-mingw32-g++-posix -sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix \ No newline at end of file +sudo update-alternatives --set x86_64-w64-mingw32-g++ /usr/bin/x86_64-w64-mingw32-g++-posix diff --git a/conanfile.py b/conanfile.py index 6e3ac8a35..302aba724 100644 --- a/conanfile.py +++ b/conanfile.py @@ -70,6 +70,7 @@ class VCMI(ConanFile): self.requires("sdl_mixer/2.0.4") elif self.settings.os == "Android": # On Android SDL version must be same as version of Java wrapper for SDL in VCMI source code + # Wrapper can be found in following directory: android/vcmi-app/src/main/java/org/libsdl/app self.requires("sdl/2.26.5") self.requires("sdl_mixer/2.0.4") else: From 69b6e9c167c1f8fa008be50dcbee42c91e341141 Mon Sep 17 00:00:00 2001 From: Dydzio Date: Mon, 14 Oct 2024 17:19:34 +0200 Subject: [PATCH 50/69] Count days from 1 instead of 0 in map editor timed event UI --- mapeditor/mapsettings/timedevent.cpp | 4 ++-- mapeditor/mapsettings/timedevent.ui | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/mapeditor/mapsettings/timedevent.cpp b/mapeditor/mapsettings/timedevent.cpp index 083bd1d72..772eea5c3 100644 --- a/mapeditor/mapsettings/timedevent.cpp +++ b/mapeditor/mapsettings/timedevent.cpp @@ -28,7 +28,7 @@ TimedEvent::TimedEvent(QListWidgetItem * t, QWidget *parent) : ui->eventMessageText->setPlainText(params.value("message").toString()); ui->eventAffectsCpu->setChecked(params.value("computerAffected").toBool()); ui->eventAffectsHuman->setChecked(params.value("humanAffected").toBool()); - ui->eventFirstOccurrence->setValue(params.value("firstOccurrence").toInt()); + ui->eventFirstOccurrence->setValue(params.value("firstOccurrence").toInt() + 1); ui->eventRepeatAfter->setValue(params.value("nextOccurrence").toInt()); auto playerList = params.value("players").toList(); @@ -68,7 +68,7 @@ void TimedEvent::on_TimedEvent_finished(int result) descriptor["message"] = ui->eventMessageText->toPlainText(); descriptor["humanAffected"] = QVariant::fromValue(ui->eventAffectsHuman->isChecked()); descriptor["computerAffected"] = QVariant::fromValue(ui->eventAffectsCpu->isChecked()); - descriptor["firstOccurrence"] = QVariant::fromValue(ui->eventFirstOccurrence->value()); + descriptor["firstOccurrence"] = QVariant::fromValue(ui->eventFirstOccurrence->value() - 1); descriptor["nextOccurrence"] = QVariant::fromValue(ui->eventRepeatAfter->value()); QVariantList players; diff --git a/mapeditor/mapsettings/timedevent.ui b/mapeditor/mapsettings/timedevent.ui index 4fef09168..104dd16b5 100644 --- a/mapeditor/mapsettings/timedevent.ui +++ b/mapeditor/mapsettings/timedevent.ui @@ -72,7 +72,11 @@ - + + + 1 + + From 3f59942b04ffe8d85fd03c27663bbde564fb2fa3 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 14 Oct 2024 19:28:38 +0200 Subject: [PATCH 51/69] code review --- client/media/CSoundHandler.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/client/media/CSoundHandler.cpp b/client/media/CSoundHandler.cpp index a0b5e6301..adfb1a2f7 100644 --- a/client/media/CSoundHandler.cpp +++ b/client/media/CSoundHandler.cpp @@ -153,14 +153,15 @@ uint32_t CSoundHandler::getSoundDurationMilliseconds(const AudioPath & sound) int freq = 0; Uint16 fmt = 0; - int chans = 0; - if(!Mix_QuerySpec(&freq, &fmt, &chans)) + int channels = 0; + if(!Mix_QuerySpec(&freq, &fmt, &channels)) return 0; if(chunk != nullptr) { - Uint32 points = (chunk->alen / ((fmt & 0xFF) / 8)); - Uint32 frames = (points / chans); + Uint32 sampleSizeBytes = (fmt & 0xFF) / 8; + Uint32 samples = (chunk->alen / sampleSizeBytes); + Uint32 frames = (samples / channels); milliseconds = ((frames * 1000) / freq); Mix_FreeChunk(chunk); From 129f8e6f34eb5e52c413fe568bfac2f4a69c0f5b Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 14 Oct 2024 19:30:03 +0200 Subject: [PATCH 52/69] code review Co-authored-by: Ivan Savenko --- lib/CGameInfoCallback.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index 9837848db..cc8572f57 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -484,7 +484,7 @@ std::vector> CGameInfoCallback::getAllVisit { std::vector> ret; for(auto & obj : gs->map->objects) - if(obj->isVisitable() && obj->ID != Obj::EVENT && getTile(obj->pos, false)) + if(obj->isVisitable() && obj->ID != Obj::EVENT && isVisible(obj)) ret.push_back(obj); return ret; From b2da3179067b320e1fd4334006f39f03bdb5c904 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:26:31 +0200 Subject: [PATCH 53/69] fixes audio playback after using Back button --- client/lobby/CBonusSelection.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/client/lobby/CBonusSelection.cpp b/client/lobby/CBonusSelection.cpp index 32ceab982..e04b19f8c 100644 --- a/client/lobby/CBonusSelection.cpp +++ b/client/lobby/CBonusSelection.cpp @@ -38,6 +38,7 @@ #include "../gui/CGuiHandler.h" #include "../gui/Shortcut.h" #include "../gui/WindowHandler.h" +#include "../adventureMap/AdventureMapInterface.h" #include "../../lib/CConfigHandler.h" #include "../../lib/CCreatureHandler.h" @@ -389,10 +390,13 @@ void CBonusSelection::goBack() if(CSH->getState() != EClientState::GAMEPLAY) { GH.windows().popWindows(2); + CMM->playMusic(); } else { close(); + if(adventureInt) + adventureInt->onAudioResumed(); } // TODO: we can actually only pop bonus selection interface for custom campaigns // Though this would require clearing CLobbyScreen::bonusSel pointer when poping this interface @@ -403,7 +407,6 @@ void CBonusSelection::goBack() CSH->state = EClientState::LOBBY; } */ - CMM->playMusic(); } void CBonusSelection::startMap() From 6e65eaafbccafb01d5c0c0c05cd7bb7daeb8bc74 Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:59:09 +0200 Subject: [PATCH 54/69] workaround for assert --- lib/texts/TextLocalizationContainer.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/texts/TextLocalizationContainer.cpp b/lib/texts/TextLocalizationContainer.cpp index 34259bfb4..eff0a692e 100644 --- a/lib/texts/TextLocalizationContainer.cpp +++ b/lib/texts/TextLocalizationContainer.cpp @@ -107,7 +107,7 @@ void TextLocalizationContainer::registerString(const std::string & identifierMod assert(!identifierModContext.empty()); assert(!localizedStringModContext.empty()); assert(UID.get().find("..") == std::string::npos); // invalid identifier - there is section that was evaluated to empty string - assert(stringsLocalizations.count(UID.get()) == 0 || boost::algorithm::starts_with(UID.get(), "map")); // registering already registered string? + assert(stringsLocalizations.count(UID.get()) == 0 || boost::algorithm::starts_with(UID.get(), "map") || boost::algorithm::starts_with(UID.get(), "header")); // registering already registered string? FIXME: "header" is a workaround. VMAP needs proper integration in translation system if(stringsLocalizations.count(UID.get()) > 0) { From cb6fa74cc41890ccce3a6dc115d313af79e57ddd Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 14 Oct 2024 20:47:06 +0200 Subject: [PATCH 55/69] lower background music while campaign audio plays --- client/mainmenu/CPrologEpilogVideo.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/client/mainmenu/CPrologEpilogVideo.cpp b/client/mainmenu/CPrologEpilogVideo.cpp index 3b68e5536..54992cf54 100644 --- a/client/mainmenu/CPrologEpilogVideo.cpp +++ b/client/mainmenu/CPrologEpilogVideo.cpp @@ -48,6 +48,7 @@ CPrologEpilogVideo::CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::f if (videoPlayer->pos.h == 400) videoPlayer->moveBy(Point(0, 100)); + CCS->musich->setVolume(CCS->musich->getVolume() / 2); // background volume is too loud by default CCS->musich->playMusic(spe.prologMusic, true, true); voiceDurationMilliseconds = CCS->soundh->getSoundDurationMilliseconds(spe.prologVoice); voiceSoundHandle = CCS->soundh->playSound(spe.prologVoice); @@ -88,6 +89,7 @@ void CPrologEpilogVideo::show(Canvas & to) void CPrologEpilogVideo::clickPressed(const Point & cursorPosition) { + CCS->musich->setVolume(CCS->musich->getVolume() * 2); // restore background volume close(); CCS->soundh->resetCallback(voiceSoundHandle); // reset callback to avoid memory corruption since 'this' will be destroyed CCS->soundh->stopSound(voiceSoundHandle); From d65938fa17b6b5f205e76473694ca91d5d7ec7bb Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Mon, 14 Oct 2024 23:26:24 +0200 Subject: [PATCH 56/69] fix campaign video scrolling for short texts --- client/mainmenu/CPrologEpilogVideo.cpp | 5 ++++- client/widgets/TextControls.cpp | 5 +++++ client/widgets/TextControls.h | 1 + 3 files changed, 10 insertions(+), 1 deletion(-) diff --git a/client/mainmenu/CPrologEpilogVideo.cpp b/client/mainmenu/CPrologEpilogVideo.cpp index 3b68e5536..7e6f47e45 100644 --- a/client/mainmenu/CPrologEpilogVideo.cpp +++ b/client/mainmenu/CPrologEpilogVideo.cpp @@ -59,7 +59,10 @@ CPrologEpilogVideo::CPrologEpilogVideo(CampaignScenarioPrologEpilog _spe, std::f CCS->soundh->setCallback(voiceSoundHandle, onVoiceStop); text = std::make_shared(Rect(100, 500, 600, 100), EFonts::FONT_BIG, ETextAlignment::CENTER, Colors::METALLIC_GOLD, spe.prologText.toString()); - text->scrollTextTo(-50); // beginning of text in the vertical middle of black area + if(text->getLines().size() == 3) + text->scrollTextTo(-25); // beginning of text in the vertical middle of black area + else if(text->getLines().size() > 3) + text->scrollTextTo(-50); // beginning of text in the vertical middle of black area } void CPrologEpilogVideo::tick(uint32_t msPassed) diff --git a/client/widgets/TextControls.cpp b/client/widgets/TextControls.cpp index 2fa440955..16745214f 100644 --- a/client/widgets/TextControls.cpp +++ b/client/widgets/TextControls.cpp @@ -176,6 +176,11 @@ void CMultiLineLabel::setText(const std::string & Txt) CLabel::setText(Txt); } +std::vector CMultiLineLabel::getLines() +{ + return lines; +} + void CTextContainer::blitLine(Canvas & to, Rect destRect, std::string what) { const auto f = GH.renderHandler().loadFont(font); diff --git a/client/widgets/TextControls.h b/client/widgets/TextControls.h index 6880e6b44..0c99c193b 100644 --- a/client/widgets/TextControls.h +++ b/client/widgets/TextControls.h @@ -96,6 +96,7 @@ public: CMultiLineLabel(Rect position, EFonts Font = FONT_SMALL, ETextAlignment Align = ETextAlignment::TOPLEFT, const ColorRGBA & Color = Colors::WHITE, const std::string & Text = ""); void setText(const std::string & Txt) override; + std::vector getLines(); void showAll(Canvas & to) override; void setVisibleSize(Rect visibleSize, bool redrawElement = true); From 6c4e7f8058c13d2fae423ce4dc3d1fff91d22f6a Mon Sep 17 00:00:00 2001 From: Olegmods Date: Tue, 15 Oct 2024 11:09:14 +0300 Subject: [PATCH 57/69] Update obstacles.json --- config/obstacles.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/obstacles.json b/config/obstacles.json index 52c8de672..b9d5bc57d 100644 --- a/config/obstacles.json +++ b/config/obstacles.json @@ -538,7 +538,7 @@ }, "55": { - "allowedTerrains" : ["water"], + "specialBattlefields" : ["ship"], "width" : 3, "height" : 3, "blockedTiles" : [-15, -16, -33], From 5f34d3b06775d7948c841f05587de383fe3155e1 Mon Sep 17 00:00:00 2001 From: Olegmods Date: Tue, 15 Oct 2024 14:15:43 +0300 Subject: [PATCH 58/69] Update obstacles.json --- config/obstacles.json | 1 + 1 file changed, 1 insertion(+) diff --git a/config/obstacles.json b/config/obstacles.json index b9d5bc57d..95cfdfd20 100644 --- a/config/obstacles.json +++ b/config/obstacles.json @@ -538,6 +538,7 @@ }, "55": { + "allowedTerrains" : ["water"], "specialBattlefields" : ["ship"], "width" : 3, "height" : 3, From 86d5c05ffa3535444783cc6de36435bba56e5736 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sat, 12 Oct 2024 21:20:29 +0300 Subject: [PATCH 59/69] Fused identical artifacts --- Mods/vcmi/config/vcmi/english.json | 1 + client/ArtifactsUIController.cpp | 5 ++- client/widgets/CArtPlace.cpp | 14 ++++-- client/widgets/CArtifactsOfHeroBase.cpp | 10 ++++- config/schemas/artifact.json | 4 ++ lib/ArtifactUtils.cpp | 14 +++--- lib/CArtHandler.cpp | 59 ++++++++++++++----------- lib/CArtHandler.h | 6 +-- lib/networkPacks/NetPacksLib.cpp | 12 ++--- 9 files changed, 72 insertions(+), 53 deletions(-) diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index ce9bc9e45..f6cff35ca 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -356,6 +356,7 @@ "vcmi.heroWindow.sortBackpackBySlot.help" : "Sort artifacts in backpack by equipped slot.", "vcmi.heroWindow.sortBackpackByClass.hover" : "Sort by class", "vcmi.heroWindow.sortBackpackByClass.help" : "Sort artifacts in backpack by artifact class. Treasure, Minor, Major, Relic", + "vcmi.heroWindow.fusingArtifact.fusing" : "You possess all of the components needed for the fusion of the %s. Do you wish to perform the fusion? {All components will be consumed upon fusion.}", "vcmi.tavernWindow.inviteHero" : "Invite hero", diff --git a/client/ArtifactsUIController.cpp b/client/ArtifactsUIController.cpp index 30374ebc2..649cd7304 100644 --- a/client/ArtifactsUIController.cpp +++ b/client/ArtifactsUIController.cpp @@ -74,7 +74,10 @@ bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const Art MetaString message = MetaString::createFromTextID(art->artType->getDescriptionTextID()); message.appendEOL(); message.appendEOL(); - message.appendRawString(CGI->generaltexth->allTexts[732]); // You possess all of the components needed to assemble the + if(combinedArt->isFused()) + message.appendRawString(CGI->generaltexth->translate("vcmi.heroWindow.fusingArtifact.fusing")); + else + message.appendRawString(CGI->generaltexth->allTexts[732]); // You possess all of the components needed to assemble the message.replaceName(ArtifactID(combinedArt->getId())); LOCPLINT->showYesNoDialog(message.toString(), [&assembleConfirmed, hero, slot, combinedArt]() { diff --git a/client/widgets/CArtPlace.cpp b/client/widgets/CArtPlace.cpp index dbae173a2..954366315 100644 --- a/client/widgets/CArtPlace.cpp +++ b/client/widgets/CArtPlace.cpp @@ -217,9 +217,9 @@ void CArtPlace::setGestureCallback(const ClickFunctor & callback) void CArtPlace::addCombinedArtInfo(const std::map> & arts) { - for(const auto & availableArts : arts) + for(auto [combinedId, availableArts] : arts) { - const auto combinedArt = availableArts.first.toArtifact(); + const auto combinedArt = combinedId.toArtifact(); MetaString info; info.appendEOL(); info.appendEOL(); @@ -227,14 +227,20 @@ void CArtPlace::addCombinedArtInfo(const std::mapgetId()); info.appendRawString("}"); info.appendRawString(" (%d/%d)"); - info.replaceNumber(availableArts.second.size()); + info.replaceNumber(availableArts.size()); info.replaceNumber(combinedArt->getConstituents().size()); for(const auto part : combinedArt->getConstituents()) { + const auto found = std::find_if(availableArts.begin(), availableArts.end(), [part](const auto & availablePart) -> bool + { + return availablePart == part->getId() ? true : false; + }); + info.appendEOL(); - if(vstd::contains(availableArts.second, part->getId())) + if(found < availableArts.end()) { info.appendName(part->getId()); + availableArts.erase(found); } else { diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index 8318fdf89..6d857b010 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -268,11 +268,17 @@ void CArtifactsOfHeroBase::setSlotData(ArtPlacePtr artPlace, const ArtifactPosit std::map> arts; for(const auto combinedArt : slotInfo->artifact->artType->getPartOf()) { - arts.try_emplace(combinedArt->getId(), std::vector{}); + assert(combinedArt->isCombined()); + arts.try_emplace(combinedArt->getId()); + CArtifactFittingSet fittingSet(*curHero); for(const auto part : combinedArt->getConstituents()) { - if(curHero->hasArt(part->getId(), false, false)) + const auto partSlot = fittingSet.getArtPos(part->getId(), false, false); + if(partSlot != ArtifactPosition::PRE_FIRST) + { arts.at(combinedArt->getId()).emplace_back(part->getId()); + fittingSet.lockSlot(partSlot); + } } } artPlace->addCombinedArtInfo(arts); diff --git a/config/schemas/artifact.json b/config/schemas/artifact.json index ab335a5ca..7143ddecc 100644 --- a/config/schemas/artifact.json +++ b/config/schemas/artifact.json @@ -61,6 +61,10 @@ "description" : "Optional, list of components for combinational artifacts", "items" : { "type" : "string" } }, + "fusedComponents" : { + "type" : "boolean", + "description" : "Used together with components fild. Marks the artifact as fused. Cannot be disassembled." + }, "bonuses" : { "type" : "array", "description" : "Bonuses provided by this artifact using bonus system", diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index 7c95e435a..bfdb48468 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -202,21 +202,23 @@ DLL_LINKAGE std::vector ArtifactUtils::assemblyPossibilities( if(art->isCombined()) return arts; - for(const auto artifact : art->getPartOf()) + for(const auto combinedArt : art->getPartOf()) { - assert(artifact->isCombined()); + assert(combinedArt->isCombined()); bool possible = true; - - for(const auto constituent : artifact->getConstituents()) //check if all constituents are available + CArtifactFittingSet fittingSet(*artSet); + for(const auto part : combinedArt->getConstituents()) // check if all constituents are available { - if(!artSet->hasArt(constituent->getId(), onlyEquiped, false)) + const auto slot = fittingSet.getArtPos(part->getId(), onlyEquiped, false); + if(slot == ArtifactPosition::PRE_FIRST) { possible = false; break; } + fittingSet.lockSlot(slot); } if(possible) - arts.push_back(artifact); + arts.push_back(combinedArt); } return arts; } diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index f96e17f83..1cd5afdda 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -56,7 +56,7 @@ const std::vector & CCombinedArtifact::getConstituents() const return constituents; } -const std::vector & CCombinedArtifact::getPartOf() const +const std::set & CCombinedArtifact::getPartOf() const { return partOf; } @@ -630,7 +630,7 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node) // when this code is called both combinational art as well as component are loaded // so it is safe to access any of them art->constituents.push_back(ArtifactID(id).toArtifact()); - objects[id]->partOf.push_back(art); + objects[id]->partOf.insert(art); }); } } @@ -784,8 +784,27 @@ bool CArtifactSet::hasArt(const ArtifactID & aid, bool onlyWorn, bool searchComb CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(const ArtifactPosition & slot, CArtifactInstance * art) { ArtPlacementMap resArtPlacement; + const auto putToSlot = [this](const ArtifactPosition & targetSlot, CArtifactInstance * targetArt, bool locked) + { + ArtSlotInfo * slotInfo; + if(targetSlot == ArtifactPosition::TRANSITION_POS) + { + slotInfo = &artifactsTransitionPos; + } + else if(ArtifactUtils::isSlotEquipment(targetSlot)) + { + slotInfo = &artifactsWorn[targetSlot]; + } + else + { + auto position = artifactsInBackpack.begin() + targetSlot - ArtifactPosition::BACKPACK_START; + slotInfo = &(*artifactsInBackpack.emplace(position)); + } + slotInfo->artifact = targetArt; + slotInfo->locked = locked; + }; - setNewArtSlot(slot, art, false); + putToSlot(slot, art, false); if(art->artType->isCombined() && ArtifactUtils::isSlotEquipment(slot)) { const CArtifactInstance * mainPart = nullptr; @@ -806,7 +825,7 @@ CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(const ArtifactPosition & partSlot = ArtifactUtils::getArtAnyPosition(this, part.art->getTypeId()); assert(ArtifactUtils::isSlotEquipment(partSlot)); - setNewArtSlot(partSlot, part.art, true); + putToSlot(partSlot, part.art, true); resArtPlacement.emplace(part.art, partSlot); } else @@ -894,7 +913,15 @@ const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const void CArtifactSet::lockSlot(const ArtifactPosition & pos) { - setNewArtSlot(pos, nullptr, true); + if(pos == ArtifactPosition::TRANSITION_POS) + artifactsTransitionPos.locked = true; + else if(ArtifactUtils::isSlotEquipment(pos)) + artifactsWorn[pos].locked = true; + else + { + assert(artifactsInBackpack.size() > pos - ArtifactPosition::BACKPACK_START); + (artifactsInBackpack.begin() + pos - ArtifactPosition::BACKPACK_START)->locked = true; + } } bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockCheck) const @@ -908,28 +935,6 @@ bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockChe return true; //no slot means not used } -void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked) -{ - assert(!vstd::contains(artifactsWorn, slot)); - - ArtSlotInfo * slotInfo; - if(slot == ArtifactPosition::TRANSITION_POS) - { - slotInfo = &artifactsTransitionPos; - } - else if(ArtifactUtils::isSlotEquipment(slot)) - { - slotInfo = &artifactsWorn[slot]; - } - else - { - auto position = artifactsInBackpack.begin() + slot - ArtifactPosition::BACKPACK_START; - slotInfo = &(*artifactsInBackpack.emplace(position)); - } - slotInfo->artifact = art; - slotInfo->locked = locked; -} - void CArtifactSet::artDeserializationFix(CBonusSystemNode *node) { for(auto & elem : artifactsWorn) diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index f0bf7d8af..a902f22c8 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -49,13 +49,13 @@ protected: CCombinedArtifact() : fused(false) {}; std::vector constituents; // Artifacts IDs a combined artifact consists of, or nullptr. - std::vector partOf; // Reverse map of constituents - combined arts that include this art + std::set partOf; // Reverse map of constituents - combined arts that include this art bool fused; public: bool isCombined() const; const std::vector & getConstituents() const; - const std::vector & getPartOf() const; + const std::set & getPartOf() const; void setFused(bool isFused); bool isFused() const; bool hasParts() const; @@ -229,8 +229,6 @@ public: const CArtifactInstance * getCombinedArtWithPart(const ArtifactID & partId) const; private: - void setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked); - void serializeJsonHero(JsonSerializeFormat & handler); void serializeJsonCreature(JsonSerializeFormat & handler); void serializeJsonCommander(JsonSerializeFormat & handler); diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index f44e6411e..0e0331d82 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -1818,14 +1818,11 @@ void AssembledArtifact::applyGs(CGameState *gs) // Find slots for all involved artifacts std::vector slotsInvolved; + CArtifactFittingSet artSet(*hero); for(const auto constituent : builtArt->getConstituents()) { - ArtifactPosition slot; - if(transformedArt->getTypeId() == constituent->getId()) - slot = transformedArtSlot; - else - slot = hero->getArtPos(constituent->getId(), false, false); - + const auto slot = artSet.getArtPos(constituent->getId(), false, false); + artSet.lockSlot(slot); assert(slot != ArtifactPosition::PRE_FIRST); slotsInvolved.emplace_back(slot); } @@ -2487,10 +2484,7 @@ void SetBankConfiguration::applyGs(CGameState *gs) const CArtifactInstance * ArtSlotInfo::getArt() const { if(locked) - { - logNetwork->warn("ArtifactLocation::getArt: This location is locked!"); return nullptr; - } return artifact; } From 049c6c539f097b77bd47d7b189be0516c99cf12d Mon Sep 17 00:00:00 2001 From: Olegmods Date: Tue, 15 Oct 2024 23:01:53 +0300 Subject: [PATCH 60/69] Revert changes --- config/obstacles.json | 1 - 1 file changed, 1 deletion(-) diff --git a/config/obstacles.json b/config/obstacles.json index 95cfdfd20..b9d5bc57d 100644 --- a/config/obstacles.json +++ b/config/obstacles.json @@ -538,7 +538,6 @@ }, "55": { - "allowedTerrains" : ["water"], "specialBattlefields" : ["ship"], "width" : 3, "height" : 3, From 5e093d82b7b1e14575d62b748319c1fa5fa8d05b Mon Sep 17 00:00:00 2001 From: Olegmods Date: Tue, 15 Oct 2024 23:02:27 +0300 Subject: [PATCH 61/69] Update battlefields.json --- config/battlefields.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config/battlefields.json b/config/battlefields.json index 9d9b12fa3..9f032e603 100644 --- a/config/battlefields.json +++ b/config/battlefields.json @@ -162,5 +162,5 @@ 159, 160, 161, 162, 163, 176, 177, 178, 179, 180] }, - "ship": { "graphics" : "CMBKDECK.BMP" } + "ship": { "graphics" : "CMBKDECK.BMP", "isSpecial" : true} } From 349f27fa52933579012606e7cd6bf798973ae0f6 Mon Sep 17 00:00:00 2001 From: George King <98261225+GeorgeK1ng@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:17:41 +0200 Subject: [PATCH 62/69] Updated Czech translation --- Mods/vcmi/config/vcmi/czech.json | 406 +++++++++++++++++++++---------- 1 file changed, 274 insertions(+), 132 deletions(-) diff --git a/Mods/vcmi/config/vcmi/czech.json b/Mods/vcmi/config/vcmi/czech.json index 57625bd43..378961136 100644 --- a/Mods/vcmi/config/vcmi/czech.json +++ b/Mods/vcmi/config/vcmi/czech.json @@ -12,14 +12,21 @@ "vcmi.adventureMap.monsterThreat.levels.9" : "Převažující", "vcmi.adventureMap.monsterThreat.levels.10" : "Smrtelná", "vcmi.adventureMap.monsterThreat.levels.11" : "Nemožná", + "vcmi.adventureMap.monsterLevel": "\n\nÚroveň %LEVEL %TOWN %ATTACK_TYPE jednotka", + "vcmi.adventureMap.monsterMeleeType": "boj zblízka", + "vcmi.adventureMap.monsterRangedType": "dálkový útok", + "vcmi.adventureMap.search.hover": "Prohledat mapový objekt", + "vcmi.adventureMap.search.help": "Vyberte objekt na mapě pro prohledání.", "vcmi.adventureMap.confirmRestartGame" : "Jste si jisti, že chcete restartovat hru?", - "vcmi.adventureMap.noTownWithMarket" : "Nejsou dostupná jakákoliv tržiště!", - "vcmi.adventureMap.noTownWithTavern" : "Nejsou dostupná jakákoliv města s krčmou!", + "vcmi.adventureMap.noTownWithMarket" : "Nejsou dostupné žádne tržnice!", + "vcmi.adventureMap.noTownWithTavern" : "Nejsou dostupná žádná města s putykou!", "vcmi.adventureMap.spellUnknownProblem" : "Neznámý problém s tímto kouzlem! Další informace nejsou k dispozici.", "vcmi.adventureMap.playerAttacked" : "Hráč byl napaden: %s", "vcmi.adventureMap.moveCostDetails" : "Body pohybu - Cena: %TURNS tahů + %POINTS bodů, zbylé body: %REMAINING", "vcmi.adventureMap.moveCostDetailsNoTurns" : "Body pohybu - Cena: %POINTS bodů, zbylé body: %REMAINING", + "vcmi.adventureMap.movementPointsHeroInfo" : "(Body pohybu: %REMAINING / %POINTS)", + "vcmi.adventureMap.replayOpponentTurnNotImplemented" : "Omlouváme se, přehrání tahu soupeře ještě není implementováno!", "vcmi.capitalColors.0" : "Červený", "vcmi.capitalColors.1" : "Modrý", @@ -29,7 +36,7 @@ "vcmi.capitalColors.5" : "Fialový", "vcmi.capitalColors.6" : "Tyrkysový", "vcmi.capitalColors.7" : "Růžový", - + "vcmi.heroOverview.startingArmy" : "Počáteční jednotky", "vcmi.heroOverview.warMachine" : "Bojové stroje", "vcmi.heroOverview.secondarySkills" : "Druhotné schopnosti", @@ -41,11 +48,11 @@ "vcmi.radialWheel.splitUnitEqually" : "Rozdělit jednotky rovnoměrně", "vcmi.radialWheel.moveUnit" : "Přesunout jednotky do jiného oddílu", "vcmi.radialWheel.splitUnit" : "Rozdělit jednotku do jiné pozice", - + "vcmi.radialWheel.heroGetArmy" : "Získat armádu jiného hrdiny", "vcmi.radialWheel.heroSwapArmy" : "Vyměnit armádu s jiným hrdinou", "vcmi.radialWheel.heroExchange" : "Otevřít výměnu hrdinů", - "vcmi.radialWheel.heroGetArtifacts" : "Získat artefakty od jiního hrdiny", + "vcmi.radialWheel.heroGetArtifacts" : "Získat artefakty od jiného hrdiny", "vcmi.radialWheel.heroSwapArtifacts" : "Vyměnit artefakty s jiným hrdinou", "vcmi.radialWheel.heroDismiss" : "Propustit hrdinu", @@ -56,6 +63,13 @@ "vcmi.spellBook.search" : "hledat...", + "vcmi.spellResearch.canNotAfford" : "Nemáte dostatek prostředků k nahrazení {%SPELL1} za {%SPELL2}. Stále však můžete toto kouzlo zrušit a pokračovat ve výzkumu kouzel.", + "vcmi.spellResearch.comeAgain" : "Výzkum už byl dnes proveden. Vraťte se zítra.", + "vcmi.spellResearch.pay" : "Chcete nahradit {%SPELL1} za {%SPELL2}? Nebo zrušit toto kouzlo a pokračovat ve výzkumu kouzel?", + "vcmi.spellResearch.research" : "Prozkoumat toto kouzlo", + "vcmi.spellResearch.skip" : "Přeskočit toto kouzlo", + "vcmi.spellResearch.abort" : "Přerušit", + "vcmi.mainMenu.serverConnecting" : "Připojování...", "vcmi.mainMenu.serverAddressEnter" : "Zadejte adresu:", "vcmi.mainMenu.serverConnectionFailed" : "Připojování selhalo", @@ -70,9 +84,14 @@ "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.backToLobby" : "Vrátit se do lobby", + "vcmi.lobby.author" : "Autor", + "vcmi.lobby.handicap" : "Handicap", + "vcmi.lobby.handicap.resource" : "Dává hráčům odpovídající zdroje navíc k běžným startovním zdrojům. Jsou povoleny záporné hodnoty, ale jsou omezeny na celkovou hodnotu 0 (hráč nikdy nezačíná se zápornými zdroji).", + "vcmi.lobby.handicap.income" : "Mění různé příjmy hráče podle procent. Výsledek je zaokrouhlen nahoru.", + "vcmi.lobby.handicap.growth" : "Mění rychlost růstu jednotel v městech vlastněných hráčem. Výsledek je zaokrouhlen nahoru.", + + "vcmi.lobby.login.title" : "Online lobby 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", @@ -135,13 +154,14 @@ "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.playerLeft" : "{Hráč opustil hru}\n\nHráč %s se odpojil ze hry!", //%s -> player color "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.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é", @@ -156,6 +176,38 @@ "vcmi.systemOptions.otherGroup" : "Ostatní nastavení", // unused right now "vcmi.systemOptions.townsGroup" : "Obrazovka města", + "vcmi.statisticWindow.statistics" : "Statistiky", + "vcmi.statisticWindow.tsvCopy" : "Zkopírovat data do schránky", + "vcmi.statisticWindow.selectView" : "Vybrat pohled", + "vcmi.statisticWindow.value" : "Hodnota", + "vcmi.statisticWindow.title.overview" : "Přehled", + "vcmi.statisticWindow.title.resources" : "Zdroje", + "vcmi.statisticWindow.title.income" : "Příjem", + "vcmi.statisticWindow.title.numberOfHeroes" : "Počet hrdinů", + "vcmi.statisticWindow.title.numberOfTowns" : "Počet měst", + "vcmi.statisticWindow.title.numberOfArtifacts" : "Počet artefaktů", + "vcmi.statisticWindow.title.numberOfDwellings" : "Počet obydlí", + "vcmi.statisticWindow.title.numberOfMines" : "Počet dolů", + "vcmi.statisticWindow.title.armyStrength" : "Síla armády", + "vcmi.statisticWindow.title.experience" : "Zkušenosti", + "vcmi.statisticWindow.title.resourcesSpentArmy" : "Náklady na armádu", + "vcmi.statisticWindow.title.resourcesSpentBuildings" : "Náklady na budovy", + "vcmi.statisticWindow.title.mapExplored" : "Prozkoumaná část mapy", + "vcmi.statisticWindow.param.playerName" : "Jméno hráče", + "vcmi.statisticWindow.param.daysSurvived" : "Počet přežitých dní", + "vcmi.statisticWindow.param.maxHeroLevel" : "Maximální úroveň hrdiny", + "vcmi.statisticWindow.param.battleWinRatioHero" : "Poměr výher (proti hrdinům)", + "vcmi.statisticWindow.param.battleWinRatioNeutral" : "Poměr výher (proti neutrálním jednotkám)", + "vcmi.statisticWindow.param.battlesHero" : "Bojů (proti hrdinům)", + "vcmi.statisticWindow.param.battlesNeutral" : "Bojů (proti neutrálním jednotkám)", + "vcmi.statisticWindow.param.maxArmyStrength" : "Maximální síla armády", + "vcmi.statisticWindow.param.tradeVolume" : "Objem obchodu", + "vcmi.statisticWindow.param.obeliskVisited" : "Navštívené obelisky", + "vcmi.statisticWindow.icon.townCaptured" : "Dobyto měst", + "vcmi.statisticWindow.icon.strongestHeroDefeated" : "Nejsilnější hrdina protivníka poražen", + "vcmi.statisticWindow.icon.grailFound" : "Nalezen Svatý grál", + "vcmi.statisticWindow.icon.defeated" : "Porážka", + "vcmi.systemOptions.fullscreenBorderless.hover" : "Celá obrazovka (bez okrajů)", "vcmi.systemOptions.fullscreenBorderless.help" : "{Celá obrazovka bez okrajů}\n\nPokud je vybráno, VCMI poběží v režimu celé obrazovky bez okrajů. V tomto režimu bude hra respektovat systémové rozlišení a ignorovat vybrané rozlišení ve hře.", "vcmi.systemOptions.fullscreenExclusive.hover" : "Celá obrazovka (exkluzivní)", @@ -169,18 +221,18 @@ "vcmi.systemOptions.scalingMenu.hover" : "Vybrat škálování rozhraní", "vcmi.systemOptions.scalingMenu.help" : "Změní škálování herního rozhraní.", "vcmi.systemOptions.longTouchButton.hover" : "Doba dlouhého podržení: %d ms", // Translation note: "ms" = "milliseconds" - "vcmi.systemOptions.longTouchButton.help" : "{Doba dlouhého podržení}\n\nPři používání dotykové obrazovky budou zobrazeno vyskakovací okno při podržení prstu na obrazovce, v milisekundách", + "vcmi.systemOptions.longTouchButton.help" : "{Doba dlouhého podržení}\n\nPři používání dotykové obrazovky bude zobrazeno vyskakovací okno při podržení prstu na obrazovce, v milisekundách", "vcmi.systemOptions.longTouchMenu.hover" : "Vybrat dobu dlouhého podržení", "vcmi.systemOptions.longTouchMenu.help" : "Změnit dobu dlouhého podržení.", "vcmi.systemOptions.longTouchMenu.entry" : "%d milisekund", "vcmi.systemOptions.framerateButton.hover" : "Zobrazit FPS", - "vcmi.systemOptions.framerateButton.help" : "{Zobrazit FPS}\n\nPřepne viditelnost počitadla snímků za sekundu v rohu obrazovky hry.", + "vcmi.systemOptions.framerateButton.help" : "{Zobrazit FPS}\n\nPřepne viditelnost počítadla snímků za sekundu v rohu obrazovky hry.", "vcmi.systemOptions.hapticFeedbackButton.hover" : "Vibrace", "vcmi.systemOptions.hapticFeedbackButton.help" : "{Vibrace}\n\nPřepnout stav vibrací při dotykovém ovládání.", "vcmi.systemOptions.enableUiEnhancementsButton.hover" : "Vylepšení rozhraní", "vcmi.systemOptions.enableUiEnhancementsButton.help" : "{Vylepšení rozhraní}\n\nZapne různá vylepšení rozhraní, jako je tlačítko batohu atd. Zakažte pro zážitek klasické hry.", "vcmi.systemOptions.enableLargeSpellbookButton.hover" : "Velká kniha kouzel", - "vcmi.systemOptions.enableLargeSpellbookButton.help" : "{Velká kniha kouzel}\n\nPovolí větší knihu kouzel, do které se jich více vleze na jednu stranu. Animace změny stránek s tímto nastavením nefunguje.", + "vcmi.systemOptions.enableLargeSpellbookButton.help" : "{Velká kniha kouzel}\n\nPovolí větší knihu kouzel, do které se vejde více kouzel na jednu stranu. Animace změny stránek s tímto nastavením nefunguje.", "vcmi.systemOptions.audioMuteFocus.hover" : "Ztlumit při neaktivitě", "vcmi.systemOptions.audioMuteFocus.help" : "{Ztlumit při neaktivitě}\n\nZtlumit zvuk, pokud je okno hry v pozadí. Výjimkou jsou zprávy ve hře a zvuk nového tahu.", @@ -194,18 +246,24 @@ "vcmi.adventureOptions.showGrid.help" : "{Zobrazit mřížku}\n\nZobrazit překrytí mřížkou, zvýrazňuje hranice mezi dlaždicemi mapy světa.", "vcmi.adventureOptions.borderScroll.hover" : "Posouvání okraji", "vcmi.adventureOptions.borderScroll.help" : "{Posouvání okraji}\n\nPosouvat mapu světa, když je kurzor na okraji obrazovky. Může být zakázáno držením klávesy CTRL.", - "vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Info Panel Creature Management", //TODO - "vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Info Panel Creature Management}\n\nAllows rearranging creatures in info panel instead of cycling between default components.", + "vcmi.adventureOptions.infoBarCreatureManagement.hover" : "Správa jednotek v informačním panelu", + "vcmi.adventureOptions.infoBarCreatureManagement.help" : "{Správa jednotek v informačním panelu}\n\nUmožňuje přeskupovat jednotky v informačním panelu namísto procházení standardních informací.", "vcmi.adventureOptions.leftButtonDrag.hover" : "Posouvání mapy levým kliknutím", "vcmi.adventureOptions.leftButtonDrag.help" : "{Posouvání mapy levým kliknutím}\n\nPosouvání mapy tažením myši se stisknutým levým tlačítkem.", + "vcmi.adventureOptions.rightButtonDrag.hover" : "Přetahování pravým tlačítkem", + "vcmi.adventureOptions.rightButtonDrag.help" : "{Přetahování pravým tlačítkem}\n\nKdyž je povoleno, pohyb myší se stisknutým pravým tlačítkem bude posouvat pohled na mapě dobrodružství.", "vcmi.adventureOptions.smoothDragging.hover" : "Plynulé posouvání mapy", "vcmi.adventureOptions.smoothDragging.help" : "{Plynulé posouvání mapy}\n\nWhen enabled, map dragging has a modern run out effect.", // TODO + "vcmi.adventureOptions.skipAdventureMapAnimations.hover" : "Přeskočit efekty mizení", + "vcmi.adventureOptions.skipAdventureMapAnimations.help" : "{Přeskočit efekty mizení}\n\nKdyž je povoleno, přeskočí se efekty mizení objektů a podobné efekty (sběr surovin, nalodění atd.). V některých případech zrychlí uživatelské rozhraní na úkor estetiky. Obzvláště užitečné v PvP hrách. Pro maximální rychlost pohybu je toto nastavení aktivní bez ohledu na další volby.", "vcmi.adventureOptions.mapScrollSpeed1.hover": "", "vcmi.adventureOptions.mapScrollSpeed5.hover": "", "vcmi.adventureOptions.mapScrollSpeed6.hover": "", "vcmi.adventureOptions.mapScrollSpeed1.help": "Nastavit posouvání mapy na velmi pomalé", "vcmi.adventureOptions.mapScrollSpeed5.help": "Nastavit posouvání mapy na velmi rychlé", "vcmi.adventureOptions.mapScrollSpeed6.help": "Nastavit posouvání mapy na okamžité", + "vcmi.adventureOptions.hideBackground.hover" : "Skrýt pozadí", + "vcmi.adventureOptions.hideBackground.help" : "{Skrýt pozadí}\n\nSkryje mapu dobrodružství na pozadí a místo ní zobrazí texturu.", "vcmi.battleOptions.queueSizeLabel.hover": "Zobrazit frontu pořadí tahů", "vcmi.battleOptions.queueSizeNoneButton.hover": "VYPNUTO", @@ -230,9 +288,13 @@ "vcmi.battleOptions.showStickyHeroInfoWindows.help": "{Zobrazit okno statistik hrdinů}\n\nTrvale zapne okno statistiky hrdinů, které ukazuje hlavní schopnosti a magickou energii.", "vcmi.battleOptions.skipBattleIntroMusic.hover": "Přeskočit úvodní hudbu", "vcmi.battleOptions.skipBattleIntroMusic.help": "{Přeskočit úvodní hudbu}\n\nPovolí akce při úvodní hudbě přehrávané při začátku každé bitvy.", + "vcmi.battleOptions.endWithAutocombat.hover": "Ukončit bitvu", + "vcmi.battleOptions.endWithAutocombat.help": "{Ukončit bitvu}\n\nAutomatický boj okamžitě dohraje bitvu do konce.", + "vcmi.battleOptions.showQuickSpell.hover": "Zobrazit rychlý panel kouzel", + "vcmi.battleOptions.showQuickSpell.help": "{Zobrazit rychlý panel kouzel}\n\nZobrazí panel pro rychlý výběr kouzel.", - "vcmi.adventureMap.revisitObject.hover" : "Znovu navštívit místo", - "vcmi.adventureMap.revisitObject.help" : "{Znovu navštívit místo}\n\nPokud se hrdina nachází na nějakém místě mapy, může jej znovu navštívit.", + "vcmi.adventureMap.revisitObject.hover" : "Znovu navštívit objekt", + "vcmi.adventureMap.revisitObject.help" : "{Znovu navštívit objekt}\n\nPokud hrdina právě stojí na objektu na mapě, může toto místo znovu navštívit.", "vcmi.battleWindow.pressKeyToSkipIntro" : "Stiskněte jakoukoliv klávesu pro okamžité zahájení bitvy", "vcmi.battleWindow.damageEstimation.melee" : "Zaútočit na %CREATURE (%DAMAGE).", @@ -245,18 +307,18 @@ "vcmi.battleWindow.damageEstimation.damage.1" : "%d poškození", "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.will" : "Provede odvetu", + "vcmi.battleWindow.damageRetaliation.may" : "Může provést odvetu", + "vcmi.battleWindow.damageRetaliation.never" : "Neprovede odvetu.", "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.battleWindow.accurateShot.resultDescription.0" : "%d %s bylo zabito přesnými zásahy!", + "vcmi.battleWindow.accurateShot.resultDescription.1" : "%d %s byl zabit přesným zásahem!", + "vcmi.battleWindow.accurateShot.resultDescription.2" : "%d %s bylo zabito přesnými zásahy!", + "vcmi.battleWindow.endWithAutocombat" : "Opravdu chcete ukončit bitvu s automatickým bojem?", "vcmi.battleResultsWindow.applyResultsLabel" : "Použít výsledek bitvy", @@ -276,26 +338,37 @@ "vcmi.otherOptions.compactTownCreatureInfo.hover": "Kompaktní informace o jednotkách", "vcmi.otherOptions.compactTownCreatureInfo.help": "{Kompaktní informace o jednotkách}\n\nZobrazit menší informace o jednotkách města v jeho přehledu (levý spodní okraj obrazovky města).", - "vcmi.townHall.missingBase" : "Základní budova %s musí být postavena jako první", - "vcmi.townHall.noCreaturesToRecruit" : "Žádné jednotky k vycvičení!", + "vcmi.townHall.missingBase" : "Nejdříve musí být postavena základní budova %s", + "vcmi.townHall.noCreaturesToRecruit" : "Nejsou k dispozici žádné jednotky k najmutí!", + + "vcmi.townStructure.bank.borrow" : "Vstupujete do banky. Bankéř vás spatří a říká: \"Máme pro vás speciální nabídku. Můžete si vzít půjčku 2500 zlata na 5 dní. Každý den budete muset splácet 500 zlata.\"", + "vcmi.townStructure.bank.payBack" : "Vstupujete do banky. Bankéř vás spatří a říká: \"Již jste si vzali půjčku. Nejprve ji splaťte, než si vezmete další.\"", "vcmi.logicalExpressions.anyOf" : "Něco z následujících:", "vcmi.logicalExpressions.allOf" : "Všechny následující:", "vcmi.logicalExpressions.noneOf" : "Žádné z následujících:", - "vcmi.heroWindow.openCommander.hover" : "Open commander info window", - "vcmi.heroWindow.openCommander.help" : "Shows details about the commander of this hero.", - "vcmi.heroWindow.openBackpack.hover" : "Open artifact backpack window", - "vcmi.heroWindow.openBackpack.help" : "Opens window that allows easier artifact backpack management.", + "vcmi.heroWindow.openCommander.hover" : "Otevřít okno s informacemi o veliteli", + "vcmi.heroWindow.openCommander.help" : "Zobrazí podrobnosti o veliteli tohoto hrdiny.", + "vcmi.heroWindow.openBackpack.hover" : "Otevřít okno s artefakty", + "vcmi.heroWindow.openBackpack.help" : "Otevře okno, které umožňuje snadnější správu artefaktů v batohu.", + "vcmi.heroWindow.sortBackpackByCost.hover" : "Seřadit podle ceny", + "vcmi.heroWindow.sortBackpackByCost.help" : "Seřadí artefakty v batohu podle ceny.", + "vcmi.heroWindow.sortBackpackBySlot.hover" : "Seřadit podle slotu", + "vcmi.heroWindow.sortBackpackBySlot.help" : "Seřadí artefakty v batohu podle přiřazeného slotu.", + "vcmi.heroWindow.sortBackpackByClass.hover" : "Seřadit podle třídy", + "vcmi.heroWindow.sortBackpackByClass.help" : "Seřadí artefakty v batohu podle třídy artefaktu. Poklad, Menší, Větší, Relikvie.", - "vcmi.commanderWindow.artifactMessage" : "Chcete navrátit tento artefakt hrdinovi?", + "vcmi.tavernWindow.inviteHero" : "Pozvat hrdinu", + + "vcmi.commanderWindow.artifactMessage" : "Chcete tento artefakt vrátit hrdinovi?", "vcmi.creatureWindow.showBonuses.hover" : "Přepnout na zobrazení bonusů", - "vcmi.creatureWindow.showBonuses.help" : "Display all active bonuses of the commander.", - "vcmi.creatureWindow.showSkills.hover" : "Přepnout na zobrazení schoostí", - "vcmi.creatureWindow.showSkills.help" : "Display all learned skills of the commander.", + "vcmi.creatureWindow.showBonuses.help" : "Zobrazí všechny aktivní bonusy velitele.", + "vcmi.creatureWindow.showSkills.hover" : "Přepnout na zobrazení dovedností", + "vcmi.creatureWindow.showSkills.help" : "Zobrazí všechny naučené dovednosti velitele.", "vcmi.creatureWindow.returnArtifact.hover" : "Vrátit artefakt", - "vcmi.creatureWindow.returnArtifact.help" : "Klikněte na toto tlačítko pro navrácení artefaktů do hrdinova batohu.", + "vcmi.creatureWindow.returnArtifact.help" : "Klikněte na toto tlačítko pro vrácení artefaktu do batohu hrdiny.", "vcmi.questLog.hideComplete.hover" : "Skrýt dokončené úkoly", "vcmi.questLog.hideComplete.help" : "Skrýt všechny dokončené úkoly.", @@ -371,9 +444,9 @@ "vcmi.optionsTab.extraOptions.help" : "Další herní možnosti", "vcmi.optionsTab.cheatAllowed.hover" : "Povolit cheaty", - "vcmi.optionsTab.unlimitedReplay.hover" : "Unlimited battle replay", + "vcmi.optionsTab.unlimitedReplay.hover" : "Neomezené opakování bitvy", "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.", + "vcmi.optionsTab.unlimitedReplay.help" : "{Neomezené opakování bitvy}\nŽádné omezení pro opakování bitev.", // 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!", @@ -383,9 +456,10 @@ "vcmi.map.victoryCondition.collectArtifacts.message" : "Získejte tři artefakty", "vcmi.map.victoryCondition.angelicAlliance.toSelf" : "Gratulace! Všichni vaši nepřítelé byli poraženi a máte Andělskou alianci! Vítězství je vaše!", "vcmi.map.victoryCondition.angelicAlliance.message" : "Porazte všechny nepřátele a utužte Andělskou alianci", + "vcmi.map.victoryCondition.angelicAlliancePartLost.toSelf" : "Bohužel, ztratili jste část Andělské aliance. Vše je ztraceno.", // few strings from WoG used by vcmi - "vcmi.stackExperience.description" : "» P o d r o b n o s t i z k u š e n o s t í o d d í l u «\n\nDruh bojovníka ................... : %s\nÚroveň hodnosti ................. : %s (%i)\nBody zkušeností ............... : %i\nZkušenostních bodů do další úrovně hodnosti .. : %i\nMaximum zkušeností na bitvu ... : %i%% (%i)\nPočet bojovníků v oddílu .... : %i\nMaximum nových rekrutů\n bez ztráty současné hodnosti .... : %i\nNásobič zkušeností ........... : %.2f\nNásobič vylepšení .............. : %.2f\nZkušnosti po 10. úrovně hodnosti ........ : %i\nMaximální počet nových rekrutů pro zachování\n 10. úrovně hodnosti s maximálními zkušenostmi: %i", + "vcmi.stackExperience.description" : "» P o d r o b n o s t i z k u š e n o s t í o d d í l u «\n\nDruh bojovníka ................... : %s\nÚroveň hodnosti ................. : %s (%i)\nBody zkušeností ............... : %i\nZkušenostních bodů do další úrovně hodnosti .. : %i\nMaximum zkušeností na bitvu ... : %i%% (%i)\nPočet jednotek v oddílu .... : %i\nMaximum nových rekrutů\n bez ztráty současné hodnosti .... : %i\nNásobič zkušeností ........... : %.2f\nNásobič vylepšení .............. : %.2f\nZkušnosti po 10. úrovně hodnosti ........ : %i\nMaximální počet nových rekrutů pro zachování\n 10. úrovně hodnosti s maximálními zkušenostmi: %i", "vcmi.stackExperience.rank.0" : "Začátečník", "vcmi.stackExperience.rank.1" : "Učeň", "vcmi.stackExperience.rank.2" : "Trénovaný", @@ -398,151 +472,219 @@ "vcmi.stackExperience.rank.9" : "Mistr", "vcmi.stackExperience.rank.10" : "Eso", - "core.bonus.ADDITIONAL_ATTACK.name": "Dvojitý úder", + // Strings for HotA Seer Hut / Quest Guards + "core.seerhut.quest.heroClass.complete.0" : "Ah, vy jste %s. Tady máte dárek. Přijmete ho?", + "core.seerhut.quest.heroClass.complete.1" : "Ah, vy jste %s. Tady máte dárek. Přijmete ho?", + "core.seerhut.quest.heroClass.complete.2" : "Ah, vy jste %s. Tady máte dárek. Přijmete ho?", + "core.seerhut.quest.heroClass.complete.3" : "Stráže si všimly, že jste %s a nabízejí vám průchod. Přijmete to?", + "core.seerhut.quest.heroClass.complete.4" : "Stráže si všimly, že jste %s a nabízejí vám průchod. Přijmete to?", + "core.seerhut.quest.heroClass.complete.5" : "Stráže si všimly, že jste %s a nabízejí vám průchod. Přijmete to?", + "core.seerhut.quest.heroClass.description.0" : "Pošlete %s do %s", + "core.seerhut.quest.heroClass.description.1" : "Pošlete %s do %s", + "core.seerhut.quest.heroClass.description.2" : "Pošlete %s do %s", + "core.seerhut.quest.heroClass.description.3" : "Pošlete %s, aby otevřel bránu", + "core.seerhut.quest.heroClass.description.4" : "Pošlete %s, aby otevřel bránu", + "core.seerhut.quest.heroClass.description.5" : "Pošlete %s, aby otevřel bránu", + "core.seerhut.quest.heroClass.hover.0" : "(hledá hrdinu třídy %s)", + "core.seerhut.quest.heroClass.hover.1" : "(hledá hrdinu třídy %s)", + "core.seerhut.quest.heroClass.hover.2" : "(hledá hrdinu třídy %s)", + "core.seerhut.quest.heroClass.hover.3" : "(hledá hrdinu třídy %s)", + "core.seerhut.quest.heroClass.hover.4" : "(hledá hrdinu třídy %s)", + "core.seerhut.quest.heroClass.hover.5" : "(hledá hrdinu třídy %s)", + "core.seerhut.quest.heroClass.receive.0" : "Mám dárek pro %s.", + "core.seerhut.quest.heroClass.receive.1" : "Mám dárek pro %s.", + "core.seerhut.quest.heroClass.receive.2" : "Mám dárek pro %s.", + "core.seerhut.quest.heroClass.receive.3" : "Stráže říkají, že průchod povolí pouze %s.", + "core.seerhut.quest.heroClass.receive.4" : "Stráže říkají, že průchod povolí pouze %s.", + "core.seerhut.quest.heroClass.receive.5" : "Stráže říkají, že průchod povolí pouze %s.", + "core.seerhut.quest.heroClass.visit.0" : "Nejste %s. Nemám pro vás nic. Zmizte!", + "core.seerhut.quest.heroClass.visit.1" : "Nejste %s. Nemám pro vás nic. Zmizte!", + "core.seerhut.quest.heroClass.visit.2" : "Nejste %s. Nemám pro vás nic. Zmizte!", + "core.seerhut.quest.heroClass.visit.3" : "Stráže zde povolí průchod pouze %s.", + "core.seerhut.quest.heroClass.visit.4" : "Stráže zde povolí průchod pouze %s.", + "core.seerhut.quest.heroClass.visit.5" : "Stráže zde povolí průchod pouze %s.", + + "core.seerhut.quest.reachDate.complete.0" : "Jsem nyní volný. Tady máte, co jsem pro vás měl. Přijmete to?", + "core.seerhut.quest.reachDate.complete.1" : "Jsem nyní volný. Tady máte, co jsem pro vás měl. Přijmete to?", + "core.seerhut.quest.reachDate.complete.2" : "Jsem nyní volný. Tady máte, co jsem pro vás měl. Přijmete to?", + "core.seerhut.quest.reachDate.complete.3" : "Nyní můžete projít. Chcete pokračovat?", + "core.seerhut.quest.reachDate.complete.4" : "Nyní můžete projít. Chcete pokračovat?", + "core.seerhut.quest.reachDate.complete.5" : "Nyní můžete projít. Chcete pokračovat?", + "core.seerhut.quest.reachDate.description.0" : "Čekejte do %s pro %s", + "core.seerhut.quest.reachDate.description.1" : "Čekejte do %s pro %s", + "core.seerhut.quest.reachDate.description.2" : "Čekejte do %s pro %s", + "core.seerhut.quest.reachDate.description.3" : "Čekejte do %s, abyste otevřeli bránu", + "core.seerhut.quest.reachDate.description.4" : "Čekejte do %s, abyste otevřeli bránu", + "core.seerhut.quest.reachDate.description.5" : "Čekejte do %s, abyste otevřeli bránu", + "core.seerhut.quest.reachDate.hover.0" : "(Vraťte se nejdříve %s)", + "core.seerhut.quest.reachDate.hover.1" : "(Vraťte se nejdříve %s)", + "core.seerhut.quest.reachDate.hover.2" : "(Vraťte se nejdříve %s)", + "core.seerhut.quest.reachDate.hover.3" : "(Vraťte se nejdříve %s)", + "core.seerhut.quest.reachDate.hover.4" : "(Vraťte se nejdříve %s)", + "core.seerhut.quest.reachDate.hover.5" : "(Vraťte se nejdříve %s)", + "core.seerhut.quest.reachDate.receive.0" : "Jsem zaneprázdněný. Vraťte se nejdříve %s", + "core.seerhut.quest.reachDate.receive.1" : "Jsem zaneprázdněný. Vraťte se nejdříve %s", + "core.seerhut.quest.reachDate.receive.2" : "Jsem zaneprázdněný. Vraťte se nejdříve %s", + "core.seerhut.quest.reachDate.receive.3" : "Zavřeno do %s.", + "core.seerhut.quest.reachDate.receive.4" : "Zavřeno do %s.", + "core.seerhut.quest.reachDate.receive.5" : "Zavřeno do %s.", + "core.seerhut.quest.reachDate.visit.0" : "Jsem zaneprázdněný. Vraťte se nejdříve %s.", + "core.seerhut.quest.reachDate.visit.1" : "Jsem zaneprázdněný. Vraťte se nejdříve %s.", + "core.seerhut.quest.reachDate.visit.2" : "Jsem zaneprázdněný. Vraťte se nejdříve %s.", + "core.seerhut.quest.reachDate.visit.3" : "Zavřeno do %s.", + "core.seerhut.quest.reachDate.visit.4" : "Zavřeno do %s.", + "core.seerhut.quest.reachDate.visit.5" : "Zavřeno do %s.", + + "core.bonus.ADDITIONAL_ATTACK.name": "Dvojitý útok", "core.bonus.ADDITIONAL_ATTACK.description": "Útočí dvakrát", - "core.bonus.ADDITIONAL_RETALIATION.name": "Další odveta", - "core.bonus.ADDITIONAL_RETALIATION.description": "Může zaútočit zpět navíc ${val}x", - "core.bonus.AIR_IMMUNITY.name": "Vzdušná odolnost", - "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.ADDITIONAL_RETALIATION.name": "Další odvetné útoky", + "core.bonus.ADDITIONAL_RETALIATION.description": "Může odvetně zaútočit ${val} krát navíc", + "core.bonus.AIR_IMMUNITY.name": "Odolnost vůči vzdušné magii", + "core.bonus.AIR_IMMUNITY.description": "Imunní vůči všem kouzlům školy vzdušné magie", + "core.bonus.ATTACKS_ALL_ADJACENT.name": "Útok na všechny kolem", + "core.bonus.ATTACKS_ALL_ADJACENT.description": "Útočí na všechny sousední nepřátele", "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á 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.BLOCKS_RETALIATION.description": "Nepřítel nemůže odvetně zaútočit", + "core.bonus.BLOCKS_RANGED_RETALIATION.name": "Žádná střelecká odveta", + "core.bonus.BLOCKS_RANGED_RETALIATION.description": "Nepřítel nemůže odvetně zaútočit střeleckým útokem", "core.bonus.CATAPULT.name": "Katapult", "core.bonus.CATAPULT.description": "Útočí na ochranné hradby", "core.bonus.CHANGES_SPELL_COST_FOR_ALLY.name": "Snížit cenu kouzel (${val})", - "core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description": "Snižuje cenu energie hrdiny o ${val}", + "core.bonus.CHANGES_SPELL_COST_FOR_ALLY.description": "Snižuje náklady na kouzla pro hrdinu o ${val}", "core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.name": "Tlumič magie (${val})", - "core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description": "Zvyšuje cenu energie kouzlení nepřítele o ${val}", - "core.bonus.CHARGE_IMMUNITY.name": "Immune to Charge", // TODO - "core.bonus.CHARGE_IMMUNITY.description": "Immune to Cavalier's and Champion's Charge", + "core.bonus.CHANGES_SPELL_COST_FOR_ENEMY.description": "Zvyšuje náklady na kouzla nepřítele o ${val}", + "core.bonus.CHARGE_IMMUNITY.name": "Odolnost vůči Nájezdu", + "core.bonus.CHARGE_IMMUNITY.description": "Imunní vůči Nájezdu Jezdců a Šampionů", "core.bonus.DARKNESS.name": "Závoj temnoty", - "core.bonus.DARKNESS.description": "Vytvoří clonu temnoty v oblasti ${val} polí", + "core.bonus.DARKNESS.description": "Vytváří závoj temnoty s poloměrem ${val}", "core.bonus.DEATH_STARE.name": "Smrtící pohled (${val}%)", - "core.bonus.DEATH_STARE.description": "Má ${val}% šanci zabít jednu creature", + "core.bonus.DEATH_STARE.description": "Má ${val}% šanci zabít jednu jednotku", "core.bonus.DEFENSIVE_STANCE.name": "Obranný bonus", - "core.bonus.DEFENSIVE_STANCE.description": "+${val} obranné síly při obraně", + "core.bonus.DEFENSIVE_STANCE.description": "+${val} k obraně při bránění", "core.bonus.DESTRUCTION.name": "Zničení", "core.bonus.DESTRUCTION.description": "Má ${val}% šanci zabít další jednotky po útoku", - "core.bonus.DOUBLE_DAMAGE_CHANCE.name": "Smrtící rána", - "core.bonus.DOUBLE_DAMAGE_CHANCE.description": "Má ${val}% šanci na udělení dvojnásobného základního poškození při útoku", - "core.bonus.DRAGON_NATURE.name": "Drak", - "core.bonus.DRAGON_NATURE.description": "Jednotka má povahu draka", - "core.bonus.EARTH_IMMUNITY.name": "Zemní odolnost", - "core.bonus.EARTH_IMMUNITY.description": "Imunní všem kouzlům školy zemské magie", + "core.bonus.DOUBLE_DAMAGE_CHANCE.name": "Smrtelný úder", + "core.bonus.DOUBLE_DAMAGE_CHANCE.description": "Má ${val}% šanci způsobit dvojnásobné základní poškození při útoku", + "core.bonus.DRAGON_NATURE.name": "Dračí povaha", + "core.bonus.DRAGON_NATURE.description": "Jednotka má Dračí povahu", + "core.bonus.EARTH_IMMUNITY.name": "Odolnost vůči zemské magii", + "core.bonus.EARTH_IMMUNITY.description": "Imunní vůči všem kouzlům školy zemské magie", "core.bonus.ENCHANTER.name": "Zaklínač", - "core.bonus.ENCHANTER.description": "Může masově seslat ${subtype.spell} každý tah", + "core.bonus.ENCHANTER.description": "Může každé kolo sesílat masové kouzlo ${subtype.spell}", "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.ENCHANTED.description": "Je pod trvalým účinkem kouzla ${subtype.spell}", + "core.bonus.ENEMY_ATTACK_REDUCTION.name": "Ignorování útoku (${val}%)", + "core.bonus.ENEMY_ATTACK_REDUCTION.description": "Při útoku je ignorováno ${val}% útočníkovy síly", + "core.bonus.ENEMY_DEFENCE_REDUCTION.name": "Ignorování obrany (${val}%)", + "core.bonus.ENEMY_DEFENCE_REDUCTION.description": "Pří útoku nebude bráno v potaz ${val}% bodů obrany obránce", + "core.bonus.FIRE_IMMUNITY.name": "Odolnost vůči ohnivé magii", + "core.bonus.FIRE_IMMUNITY.description": "Imunní vůči 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.FIRE_SHIELD.description": "Odrazí část zranění při útoku z blízka", "core.bonus.FIRST_STRIKE.name": "První úder", - "core.bonus.FIRST_STRIKE.description": "Tato jednotka provede odvetu ještě než je na ni zaútočeno", + "core.bonus.FIRST_STRIKE.description": "Tato jednotka útočí dříve, než je napadena", "core.bonus.FEAR.name": "Strach", - "core.bonus.FEAR.description": "Způsobí strach nepřátelskému oddílu", + "core.bonus.FEAR.description": "Vyvolává strach u nepřátelské jednotky", "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", - "core.bonus.FREE_SHOOTING.description": "Může použít výstřely při útoku zblízka", + "core.bonus.FEARLESS.description": "Imunní vůči schopnosti Strach", + "core.bonus.FEROCITY.name": "Zuřivost", + "core.bonus.FEROCITY.description": "Útočí ${val} krát navíc, pokud někoho zabije", + "core.bonus.FLYING.name": "Létání", + "core.bonus.FLYING.description": "Při pohybu létá (ignoruje překážky)", + "core.bonus.FREE_SHOOTING.name": "Střelba zblízka", + "core.bonus.FREE_SHOOTING.description": "Může použít výstřely i při útoku zblízka", "core.bonus.GARGOYLE.name": "Chrlič", - "core.bonus.GARGOYLE.description": "Cannot be raised or healed", // TODO + "core.bonus.GARGOYLE.description": "Nemůže být oživen ani vyléčen", "core.bonus.GENERAL_DAMAGE_REDUCTION.name": "Snižuje poškození (${val}%)", "core.bonus.GENERAL_DAMAGE_REDUCTION.description": "Snižuje poškození od útoků z dálky a blízka", - "core.bonus.HATE.name": "Nesnáší ${subtype.creature}", - "core.bonus.HATE.description": "Dává o ${val} % větší zranění jednotce ${subtype.creature}", + "core.bonus.HATE.name": "Nenávidí ${subtype.creature}", + "core.bonus.HATE.description": "Způsobuje ${val}% více poškození vůči ${subtype.creature}", "core.bonus.HEALER.name": "Léčitel", "core.bonus.HEALER.description": "Léčí spojenecké jednotky", "core.bonus.HP_REGENERATION.name": "Regenerace", - "core.bonus.HP_REGENERATION.description": "Každé kolo léčí ${val} životů", - "core.bonus.JOUSTING.name": "Nabití šampiona", + "core.bonus.HP_REGENERATION.description": "Každé kolo regeneruje ${val} bodů zdraví", + "core.bonus.JOUSTING.name": "Nájezd šampionů", "core.bonus.JOUSTING.description": "+${val}% poškození za každé projité pole", "core.bonus.KING.name": "Král", - "core.bonus.KING.description": "Zranitelný zabijákovi úrovně ${val} a vyšší", + "core.bonus.KING.description": "Zranitelný proti zabijákovi úrovně ${val} a vyšší", "core.bonus.LEVEL_SPELL_IMMUNITY.name": "Odolnost kouzel 1-${val}", "core.bonus.LEVEL_SPELL_IMMUNITY.description": "Odolnost vůči kouzlům úrovní 1-${val}", - "core.bonus.LIMITED_SHOOTING_RANGE.name" : "Omezený dosah střelby", - "core.bonus.LIMITED_SHOOTING_RANGE.description" : "Nevystřelí na jednotky dále než ${val} polí", - "core.bonus.LIFE_DRAIN.name": "Vysátí životů (${val}%)", - "core.bonus.LIFE_DRAIN.description": "Vysaje ${val}% uděleného poškození", - "core.bonus.MANA_CHANNELING.name": "${val}% kouzelný kanál", - "core.bonus.MANA_CHANNELING.description": "Dá vašemu hrdinovi ${val} % many využité nepřítelem", - "core.bonus.MANA_DRAIN.name": "Vysátí many", - "core.bonus.MANA_DRAIN.description": "Každé kolo vysaje ${val} many", - "core.bonus.MAGIC_MIRROR.name": "Kouzelné zrcadlo (${val}%)", + "core.bonus.LIMITED_SHOOTING_RANGE.name": "Omezený dostřel", + "core.bonus.LIMITED_SHOOTING_RANGE.description": "Není schopen zasáhnout jednotky vzdálenější než ${val} polí", + "core.bonus.LIFE_DRAIN.name": "Vysávání života (${val}%)", + "core.bonus.LIFE_DRAIN.description": "Vysává ${val}% způsobeného poškození", + "core.bonus.MANA_CHANNELING.name": "Kanál magie ${val}%", + "core.bonus.MANA_CHANNELING.description": "Poskytuje vašemu hrdinovi ${val}% many použité nepřítelem", + "core.bonus.MANA_DRAIN.name": "Vysávání many", + "core.bonus.MANA_DRAIN.description": "Vysává ${val} many každý tah", + "core.bonus.MAGIC_MIRROR.name": "Magické zrcadlo (${val}%)", "core.bonus.MAGIC_MIRROR.description": "Má ${val}% šanci odrazit útočné kouzlo na nepřátelskou jednotku", "core.bonus.MAGIC_RESISTANCE.name": "Magická odolnost (${val}%)", - "core.bonus.MAGIC_RESISTANCE.description": "Má ${val}% šanci ustát nepřátelské kouzlo", - "core.bonus.MIND_IMMUNITY.name": "Imunita kouzel mysli", - "core.bonus.MIND_IMMUNITY.description": "Imunní vůči kouzlům cílícím na mysl", - "core.bonus.NO_DISTANCE_PENALTY.name": "Bez penalizace vzdálenosti", - "core.bonus.NO_DISTANCE_PENALTY.description": "Plné poškození na jakoukoliv vzdálenost", + "core.bonus.MAGIC_RESISTANCE.description": "Má ${val}% šanci odolat nepřátelskému kouzlu", + "core.bonus.MIND_IMMUNITY.name": "Imunita vůči kouzlům mysli", + "core.bonus.MIND_IMMUNITY.description": "Imunní vůči kouzlům mysli", + "core.bonus.NO_DISTANCE_PENALTY.name": "Žádná penalizace vzdálenosti", + "core.bonus.NO_DISTANCE_PENALTY.description": "Způsobuje plné poškození na jakoukoliv vzdálenost", "core.bonus.NO_MELEE_PENALTY.name": "Bez penalizace útoku zblízka", "core.bonus.NO_MELEE_PENALTY.description": "Jednotka není penalizována za útok zblízka", "core.bonus.NO_MORALE.name": "Neutrální morálka", - "core.bonus.NO_MORALE.description": "Jednotka je imunní vůči efektu morálky", + "core.bonus.NO_MORALE.description": "Jednotka je imunní vůči efektům morálky", "core.bonus.NO_WALL_PENALTY.name": "Bez penalizace hradbami", - "core.bonus.NO_WALL_PENALTY.description": "Plné poškození při obléhání", - "core.bonus.NON_LIVING.name": "Neživoucí", + "core.bonus.NO_WALL_PENALTY.description": "Plné poškození během obléhání", + "core.bonus.NON_LIVING.name": "Neživý", "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á odveta", + "core.bonus.RANGED_RETALIATION.name": "Střelecká 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", + "core.bonus.RECEPTIVE.name": "Vnímavý", + "core.bonus.RECEPTIVE.description": "Nemá imunitu na přátelská kouzla", "core.bonus.REBIRTH.name": "Znovuzrození (${val}%)", - "core.bonus.REBIRTH.description": "${val}% oddílu se po smrti znovu narodí", + "core.bonus.REBIRTH.description": "${val}% jednotek povstane po smrti", "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.RETURN_AFTER_STRIKE.description": "Navrátí se po útoku na zblízka", + "core.bonus.REVENGE.name": "Pomsta", + "core.bonus.REVENGE.description": "Způsobuje extra poškození na základě ztrát útočníka v bitvě", "core.bonus.SHOOTER.name": "Střelec", "core.bonus.SHOOTER.description": "Jednotka může střílet", - "core.bonus.SHOOTS_ALL_ADJACENT.name": "Střílí okolo", - "core.bonus.SHOOTS_ALL_ADJACENT.description": "Vzdálené útoky této jednotky zasáhnou všechny cíle v malé oblasti", + "core.bonus.SHOOTS_ALL_ADJACENT.name": "Střílí všude kolem", + "core.bonus.SHOOTS_ALL_ADJACENT.description": "Střelecký útok této jednotky zasáhne všechny cíle v malé oblasti", "core.bonus.SOUL_STEAL.name": "Zloděj duší", - "core.bonus.SOUL_STEAL.description": "Získá ${val} nových jednotek za každého zabitého nepřítele", + "core.bonus.SOUL_STEAL.description": "Získává ${val} nové jednotky za každého zabitého nepřítele", "core.bonus.SPELLCASTER.name": "Kouzelník", - "core.bonus.SPELLCASTER.description": "Může seslat ${subtype.spell}", - "core.bonus.SPELL_AFTER_ATTACK.name": "Kouzlení po útoku", - "core.bonus.SPELL_AFTER_ATTACK.description": "Má ${val}% šanci seslat ${subtype.spell} po zaútočení", - "core.bonus.SPELL_BEFORE_ATTACK.name": "Kouzlení před útokem", - "core.bonus.SPELL_BEFORE_ATTACK.description": "Má ${val}% šanci seslat ${subtype.spell} před zaútočením", + "core.bonus.SPELLCASTER.description": "Může seslat kouzlo ${subtype.spell}", + "core.bonus.SPELL_AFTER_ATTACK.name": "Sesílá po útoku", + "core.bonus.SPELL_AFTER_ATTACK.description": "Má ${val}% šanci seslat ${subtype.spell} po útoku", + "core.bonus.SPELL_BEFORE_ATTACK.name": "Sesílá před útokem", + "core.bonus.SPELL_BEFORE_ATTACK.description": "Má ${val}% šanci seslat ${subtype.spell} před útokem", "core.bonus.SPELL_DAMAGE_REDUCTION.name": "Magická odolnost", - "core.bonus.SPELL_DAMAGE_REDUCTION.description": "Zranění od kouzel sníženo o ${val}%.", - "core.bonus.SPELL_IMMUNITY.name": "Odolnost vůči kouzlům", - "core.bonus.SPELL_IMMUNITY.description": "Odolnost proti ${subtype.spell}", + "core.bonus.SPELL_DAMAGE_REDUCTION.description": "Poškození kouzly sníženo o ${val}%.", + "core.bonus.SPELL_IMMUNITY.name": "Imunita vůči kouzlům", + "core.bonus.SPELL_IMMUNITY.description": "Imunní vůči ${subtype.spell}", "core.bonus.SPELL_LIKE_ATTACK.name": "Útok kouzlem", "core.bonus.SPELL_LIKE_ATTACK.description": "Útočí kouzlem ${subtype.spell}", - "core.bonus.SPELL_RESISTANCE_AURA.name": "Aura odolnosti", - "core.bonus.SPELL_RESISTANCE_AURA.description": "Oddíly poblíž získají ${val}% magickou odolnost", - "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", //TODO + "core.bonus.SPELL_RESISTANCE_AURA.name": "Aura odporu", + "core.bonus.SPELL_RESISTANCE_AURA.description": "Jednotky poblíž získají ${val}% magickou odolnost", + "core.bonus.SUMMON_GUARDIANS.name": "Přivolání ochránců", + "core.bonus.SUMMON_GUARDIANS.description": "Na začátku boje přivolá ${subtype.creature} (${val}%)", + "core.bonus.SYNERGY_TARGET.name": "Synergizovatelný", + "core.bonus.SYNERGY_TARGET.description": "Tato jednotka je náchylná k synergickým efektům", "core.bonus.TWO_HEX_ATTACK_BREATH.name": "Dech", - "core.bonus.TWO_HEX_ATTACK_BREATH.description": "Dechový útok (dosah do dvou polí)", + "core.bonus.TWO_HEX_ATTACK_BREATH.description": "Útok dechem (dosah 2 polí)", "core.bonus.THREE_HEADED_ATTACK.name": "Tříhlavý útok", "core.bonus.THREE_HEADED_ATTACK.description": "Útočí na tři sousední jednotky", "core.bonus.TRANSMUTATION.name": "Transmutace", - "core.bonus.TRANSMUTATION.description": "${val}% šance na přeměnu útočené jednotky na jiný druh", + "core.bonus.TRANSMUTATION.description": "${val}% šance na přeměnu napadené jednotky na jiný typ", "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 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.UNLIMITED_RETALIATIONS.name": "Neomezené odvetné útoky", + "core.bonus.UNLIMITED_RETALIATIONS.description": "Může provést neomezený počet odvetných útoků", + "core.bonus.WATER_IMMUNITY.name": "Odolnost vůči vodní magii", + "core.bonus.WATER_IMMUNITY.description": "Imunní vůči všem kouzlům školy vodní magie", "core.bonus.WIDE_BREATH.name": "Široký dech", - "core.bonus.WIDE_BREATH.description": "Útočí širokým dechem (více polí)" + "core.bonus.WIDE_BREATH.description": "Široký útok dechem (více polí)", + "core.bonus.DISINTEGRATE.name": "Rozpad", + "core.bonus.DISINTEGRATE.description": "Po smrti nezůstane žádné tělo", + "core.bonus.INVINCIBLE.name": "Neporazitelný", + "core.bonus.INVINCIBLE.description": "Nelze ovlivnit žádným efektem" } From 6b537319be8f8c86951aee43a67693b2edb2e14f Mon Sep 17 00:00:00 2001 From: George King <98261225+GeorgeK1ng@users.noreply.github.com> Date: Wed, 16 Oct 2024 12:24:09 +0200 Subject: [PATCH 63/69] Updated Czech translation --- Mods/vcmi/config/vcmi/czech.json | 22 +++++++++++----------- 1 file changed, 11 insertions(+), 11 deletions(-) diff --git a/Mods/vcmi/config/vcmi/czech.json b/Mods/vcmi/config/vcmi/czech.json index 378961136..90a0733a8 100644 --- a/Mods/vcmi/config/vcmi/czech.json +++ b/Mods/vcmi/config/vcmi/czech.json @@ -12,11 +12,11 @@ "vcmi.adventureMap.monsterThreat.levels.9" : "Převažující", "vcmi.adventureMap.monsterThreat.levels.10" : "Smrtelná", "vcmi.adventureMap.monsterThreat.levels.11" : "Nemožná", - "vcmi.adventureMap.monsterLevel": "\n\nÚroveň %LEVEL %TOWN %ATTACK_TYPE jednotka", - "vcmi.adventureMap.monsterMeleeType": "boj zblízka", - "vcmi.adventureMap.monsterRangedType": "dálkový útok", - "vcmi.adventureMap.search.hover": "Prohledat mapový objekt", - "vcmi.adventureMap.search.help": "Vyberte objekt na mapě pro prohledání.", + "vcmi.adventureMap.monsterLevel" : "\n\nÚroveň %LEVEL %TOWN %ATTACK_TYPE jednotka", + "vcmi.adventureMap.monsterMeleeType" : "útok zblízka", + "vcmi.adventureMap.monsterRangedType" : "útok na dálku", + "vcmi.adventureMap.search.hover" : "Prohledat mapový objekt", + "vcmi.adventureMap.search.help" : "Vyberte objekt na mapě pro prohledání.", "vcmi.adventureMap.confirmRestartGame" : "Jste si jisti, že chcete restartovat hru?", "vcmi.adventureMap.noTownWithMarket" : "Nejsou dostupné žádne tržnice!", @@ -198,8 +198,8 @@ "vcmi.statisticWindow.param.maxHeroLevel" : "Maximální úroveň hrdiny", "vcmi.statisticWindow.param.battleWinRatioHero" : "Poměr výher (proti hrdinům)", "vcmi.statisticWindow.param.battleWinRatioNeutral" : "Poměr výher (proti neutrálním jednotkám)", - "vcmi.statisticWindow.param.battlesHero" : "Bojů (proti hrdinům)", - "vcmi.statisticWindow.param.battlesNeutral" : "Bojů (proti neutrálním jednotkám)", + "vcmi.statisticWindow.param.battlesHero" : "Bitev (proti hrdinům)", + "vcmi.statisticWindow.param.battlesNeutral" : "Bitej (proti neutrálním jednotkám)", "vcmi.statisticWindow.param.maxArmyStrength" : "Maximální síla armády", "vcmi.statisticWindow.param.tradeVolume" : "Objem obchodu", "vcmi.statisticWindow.param.obeliskVisited" : "Navštívené obelisky", @@ -326,7 +326,7 @@ "vcmi.tutorialWindow.decription.RightClick" : "Klepněte a držte prvek, na který byste chtěli použít pravé tlačítko myši. Klepněte na volnou oblast pro zavření.", "vcmi.tutorialWindow.decription.MapPanning" : "Klepněte a držte jedním prstem pro posouvání mapy.", "vcmi.tutorialWindow.decription.MapZooming" : "Přibližte dva prsty k sobě pro přiblížení mapy.", - "vcmi.tutorialWindow.decription.RadialWheel" : "Přejetí otevře kruhovou nabídku pro různé akce, třeba správa hrdiny/bojovnínků a příkazy měst.", + "vcmi.tutorialWindow.decription.RadialWheel" : "Přejetí otevře kruhovou nabídku pro různé akce, třeba správa hrdiny/jednotek a příkazy měst.", "vcmi.tutorialWindow.decription.BattleDirection" : "Pro útok ze speifického úhlu, přejeďte směrem, ze kterého má být útok vykonán.", "vcmi.tutorialWindow.decription.BattleDirectionAbort" : "Gesto útoku pod úhlem může být zrušeno, pokud, pokud je prst dostatečně daleko.", "vcmi.tutorialWindow.decription.AbortSpell" : "Klepněte a držte pro zrušení kouzla.", @@ -451,7 +451,7 @@ // 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!", - "vcmi.map.victoryCondition.eliminateMonsters.toOthers" : "Nepřítel porazil všechny bojovníky zamořující tuto zemi a nárokuje si vítězství!", + "vcmi.map.victoryCondition.eliminateMonsters.toOthers" : "Nepřítel porazil všechny jednotky zamořující tuto zemi a nárokuje si vítězství!", "vcmi.map.victoryCondition.eliminateMonsters.toSelf" : "Gratulace! Porazili jste všechny nepřátele zamořující tuto zemi a můžete si nárokovat vítězství!", "vcmi.map.victoryCondition.collectArtifacts.message" : "Získejte tři artefakty", "vcmi.map.victoryCondition.angelicAlliance.toSelf" : "Gratulace! Všichni vaši nepřítelé byli poraženi a máte Andělskou alianci! Vítězství je vaše!", @@ -459,7 +459,7 @@ "vcmi.map.victoryCondition.angelicAlliancePartLost.toSelf" : "Bohužel, ztratili jste část Andělské aliance. Vše je ztraceno.", // few strings from WoG used by vcmi - "vcmi.stackExperience.description" : "» P o d r o b n o s t i z k u š e n o s t í o d d í l u «\n\nDruh bojovníka ................... : %s\nÚroveň hodnosti ................. : %s (%i)\nBody zkušeností ............... : %i\nZkušenostních bodů do další úrovně hodnosti .. : %i\nMaximum zkušeností na bitvu ... : %i%% (%i)\nPočet jednotek v oddílu .... : %i\nMaximum nových rekrutů\n bez ztráty současné hodnosti .... : %i\nNásobič zkušeností ........... : %.2f\nNásobič vylepšení .............. : %.2f\nZkušnosti po 10. úrovně hodnosti ........ : %i\nMaximální počet nových rekrutů pro zachování\n 10. úrovně hodnosti s maximálními zkušenostmi: %i", + "vcmi.stackExperience.description" : "» P o d r o b n o s t i z k u š e n o s t í o d d í l u «\n\nDruh jednotky ................... : %s\nÚroveň hodnosti ................. : %s (%i)\nBody zkušeností ............... : %i\nZkušenostních bodů do další úrovně hodnosti .. : %i\nMaximum zkušeností na bitvu ... : %i%% (%i)\nPočet jednotek v oddílu .... : %i\nMaximum nových rekrutů\n bez ztráty současné hodnosti .... : %i\nNásobič zkušeností ........... : %.2f\nNásobič vylepšení .............. : %.2f\nZkušnosti po 10. úrovně hodnosti ........ : %i\nMaximální počet nových rekrutů pro zachování\n 10. úrovně hodnosti s maximálními zkušenostmi: %i", "vcmi.stackExperience.rank.0" : "Začátečník", "vcmi.stackExperience.rank.1" : "Učeň", "vcmi.stackExperience.rank.2" : "Trénovaný", @@ -666,7 +666,7 @@ "core.bonus.SPELL_RESISTANCE_AURA.name": "Aura odporu", "core.bonus.SPELL_RESISTANCE_AURA.description": "Jednotky poblíž získají ${val}% magickou odolnost", "core.bonus.SUMMON_GUARDIANS.name": "Přivolání ochránců", - "core.bonus.SUMMON_GUARDIANS.description": "Na začátku boje přivolá ${subtype.creature} (${val}%)", + "core.bonus.SUMMON_GUARDIANS.description": "Na začátku bitvy přivolá ${subtype.creature} (${val}%)", "core.bonus.SYNERGY_TARGET.name": "Synergizovatelný", "core.bonus.SYNERGY_TARGET.description": "Tato jednotka je náchylná k synergickým efektům", "core.bonus.TWO_HEX_ATTACK_BREATH.name": "Dech", From 8904701e2e9caee7d5d6be61fbfd2f8459ed9bc5 Mon Sep 17 00:00:00 2001 From: George King <98261225+GeorgeK1ng@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:55:13 +0200 Subject: [PATCH 64/69] Updated Czech translation Added newly added "vcmi.heroWindow.fusingArtifact.fusing" translation --- Mods/vcmi/config/vcmi/czech.json | 1 + 1 file changed, 1 insertion(+) diff --git a/Mods/vcmi/config/vcmi/czech.json b/Mods/vcmi/config/vcmi/czech.json index 90a0733a8..9e72b3add 100644 --- a/Mods/vcmi/config/vcmi/czech.json +++ b/Mods/vcmi/config/vcmi/czech.json @@ -358,6 +358,7 @@ "vcmi.heroWindow.sortBackpackBySlot.help" : "Seřadí artefakty v batohu podle přiřazeného slotu.", "vcmi.heroWindow.sortBackpackByClass.hover" : "Seřadit podle třídy", "vcmi.heroWindow.sortBackpackByClass.help" : "Seřadí artefakty v batohu podle třídy artefaktu. Poklad, Menší, Větší, Relikvie.", + "vcmi.heroWindow.fusingArtifact.fusing" : "Máte všechny potřebné části k vytvoření %s. Chcete provést sloučení? {Při sloučení budou použity všechny části.}", "vcmi.tavernWindow.inviteHero" : "Pozvat hrdinu", From 21c83bd3dc26995b9002c9e5bfdf26661056e616 Mon Sep 17 00:00:00 2001 From: George King <98261225+GeorgeK1ng@users.noreply.github.com> Date: Wed, 16 Oct 2024 18:58:26 +0200 Subject: [PATCH 65/69] Updated Czech translation Updated Launcher translation --- launcher/translation/czech.ts | 121 +++++++++++++++++----------------- 1 file changed, 61 insertions(+), 60 deletions(-) diff --git a/launcher/translation/czech.ts b/launcher/translation/czech.ts index 1a47abdaf..2ccefa301 100644 --- a/launcher/translation/czech.ts +++ b/launcher/translation/czech.ts @@ -54,7 +54,7 @@ Log files directory - Složka záznamů hry + Adresář souborů s logy @@ -176,7 +176,7 @@ Creatures - Bojovníci + Jednotky @@ -209,7 +209,7 @@ Downloadable - Stahovatelné + Ke stažení @@ -219,7 +219,7 @@ Updatable - Aktualizovatelné + K aktualizaci @@ -387,12 +387,12 @@ 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 + Tato modifikace nelze nainstalovat ani povolit, protože nejsou přítomny následující závislosti 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í + Tato modifikace nemůže být povolena, protože není kompatibilní s následujícími modifikacemi @@ -407,7 +407,7 @@ 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 + Toto je podmodifikace a nelze ji nainstalovat ani odinstalovat samostatně bez hlavní modifikace @@ -442,17 +442,17 @@ Gog files - + Soubory GOG All files (*.*) - + Všechny soubory (*.*) Select files (configs, mods, maps, campaigns, gog files) to install... - + Vyberte soubory (konfigurace, modifikace, mapy, kampaně, soubory GOG) k instalaci... @@ -467,7 +467,7 @@ Downloading %1. %p% (%v MB out of %m MB) finished - + Stahování %1. %p% (%v MB z %m MB) dokončeno @@ -499,7 +499,7 @@ Nainstalovat úspěšně stažené? Installing chronicles - + Instalování kronik @@ -667,7 +667,7 @@ Nainstalovat úspěšně stažené? Downscaling Filter - + Filtr pro zmenšování @@ -677,7 +677,7 @@ Nainstalovat úspěšně stažené? Online Lobby port - Port online předsíně + Port online lobby @@ -692,7 +692,7 @@ Nainstalovat úspěšně stažené? Automatic (Linear) - + Automaticky (Lineárně) @@ -709,42 +709,42 @@ Nainstalovat úspěšně stažené? Automatic - + Automaticky Mods Validation - + Validace modifikací None - + Nic xBRZ x2 - + xBRZ x2 xBRZ x3 - + xBRZ x3 xBRZ x4 - + xBRZ x4 Full - + Plné Use scalable fonts - + Použít škálovatelná písma @@ -754,27 +754,27 @@ Nainstalovat úspěšně stažené? Cursor Scaling - + Škálování kurzoru Scalable - + Škálovatelné Miscellaneous - + Ostatní Font Scaling (experimental) - + Škálování písma (experimentální) Original - + Původní @@ -784,7 +784,7 @@ Nainstalovat úspěšně stažené? Basic - + Základní @@ -814,12 +814,12 @@ Nainstalovat úspěšně stažené? Show Tutorial again - + Znovu zobrazi Tutoriál Reset - + Restart @@ -1011,7 +1011,7 @@ Exkluzivní celá obrazovka - hra zakryje vaši celou obrazovku a použije vybra Display index - + Monitor @@ -1059,35 +1059,35 @@ Exkluzivní celá obrazovka - hra zakryje vaši celou obrazovku a použije vybra File cannot opened - + Soubor nelze otevřít Invalid file selected - Vybrán neplatný soubor + Vybrán neplatný soubor You have to select an gog installer file! - + Musíte vybrat instalační soubor GOG! You have to select an chronicle installer file! - + Musíte vybrat instalační soubor kronik! Extracting error! - + Chyb při rozbalování! Heroes Chronicles - + Heroes Chronicles @@ -1154,13 +1154,13 @@ Before you can start playing, there are a few more steps that need to be complet Please keep in mind that in order to use VCMI you must own the original data files for Heroes® of Might and Magic® III: Complete or The Shadow of Death. Heroes® of Might and Magic® III HD is currently not supported! - Děkujeme za instalaci VCMI! + Děkujeme, že jste si nainstalovali VCMI! -Před začátkem hraní musíte ještě dokončit pár kroků. +Než začnete hrát, je třeba dokončit několik kroků. -Prosíme, mějte na paměti, že abyste mohli hrát VCMI, musíte vlastnit originální datové soubory Heroes® of Might and Magic® III: Complete nebo The Shadow of Death. +Pamatujte, že pro používání VCMI musíte vlastnit originální herní soubory pro Heroes® of Might and Magic® III: Complete nebo The Shadow of Death. -Heroes® of Might and Magic® III HD není v současnosti podporovaný! +Heroes® of Might and Magic® III HD momentálně není podporováno! @@ -1175,7 +1175,7 @@ Heroes® of Might and Magic® III HD není v současnosti podporovaný! 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. + 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 @@ -1195,7 +1195,7 @@ Heroes® of Might and Magic® III HD není v současnosti podporovaný! Install a translation of Heroes III in your preferred language - Instalovat překlad Heroes III vašeho upřednostněného jazyka + Nainstalujte si překlad Heroes III dle preferovaného jazyku @@ -1222,7 +1222,7 @@ Offline instalátor obsahuje dvě části, .exe a .bin. Ujistěte se, že stahuj Optionally, you can install additional mods either now, or at any point later, using the VCMI Launcher - Nyní můžete volitelně nainstalovat další modifikace, nebo též kdykoliv potom pomocí spouštěče VCMI + Můžete si nyní, nebo kdykoliv později, nainstalovat další mody pomocí VCMI Launcheru, podle svých preferencí @@ -1232,12 +1232,12 @@ Offline instalátor obsahuje dvě části, .exe a .bin. Ujistěte se, že stahuj Install compatible version of "Horn of the Abyss", a fan-made Heroes III expansion ported by the VCMI team - + Instalovat kompatibilní verzi 'Horn of the Abyss', fanouškovského rozšíření Heroes III portovaného týmem VCMI Install compatible version of "In The Wake of Gods", a fan-made Heroes III expansion - + "Instalovat kompatibilní verzi In The Wake of Gods', fanouškovského rozšíření Heroes III portovaného týmem VCMI" @@ -1294,7 +1294,7 @@ Offline instalátor obsahuje dvě části, .exe a .bin. Ujistěte se, že stahuj Horn of the Abyss - + Horn of the Abyss @@ -1304,7 +1304,7 @@ Offline instalátor obsahuje dvě části, .exe a .bin. Ujistěte se, že stahuj In The Wake of Gods - + In The Wake of Gods @@ -1341,7 +1341,7 @@ Offline instalátor obsahuje dvě části, .exe a .bin. Ujistěte se, že stahuj File cannot be opened - + Soubor nelze otevřít @@ -1361,17 +1361,17 @@ Offline instalátor obsahuje dvě části, .exe a .bin. Ujistěte se, že stahuj You've provided GOG Galaxy installer! This file doesn't contain the game. Please download the offline backup game installer! - + Poskytli jste instalátor GOG Galaxy! Tento soubor neobsahuje hru. Prosím, stáhněte si záložní offline instalátor hry! Extracting error! - + Chyba při rozbalování! No Heroes III data! - Žádná data Heroes III! + Chybí data Heroes III! @@ -1397,15 +1397,15 @@ 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. + Soubory Heroes III HD Edice nejsou podporovány ve VCMI. +Prosím 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. +Prosím vyberte složku s Heroes III: Complete Edition nebo Heroes III: Shadow of Death. @@ -1422,17 +1422,18 @@ Prosíme vyberte složku s Heroes III: Complete Edition nebo Heroes III: Shadow Stream error while extracting files! error reason: - + Chyba při extrahování souborů! +Důvod chyby: Not a supported Inno Setup installer! - + Nepodporovaný Inno Setup instalátor! VCMI was compiled without innoextract support, which is needed to extract exe files! - + VCMI bylo zkompilováno bez podpory innoextract, která je potřebná pro extrahování EXE souborů! @@ -1533,7 +1534,7 @@ error reason: VCMI Launcher - Spouštěč VCMI + VCMI Launcher From 7c0dec1b5ee3d1943215482ca9f61b5372c9d809 Mon Sep 17 00:00:00 2001 From: George King <98261225+GeorgeK1ng@users.noreply.github.com> Date: Wed, 16 Oct 2024 19:00:13 +0200 Subject: [PATCH 66/69] Small update Updated Launcher translation --- launcher/translation/czech.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/launcher/translation/czech.ts b/launcher/translation/czech.ts index 2ccefa301..5434843d7 100644 --- a/launcher/translation/czech.ts +++ b/launcher/translation/czech.ts @@ -1195,7 +1195,7 @@ Heroes® of Might and Magic® III HD momentálně není podporováno! Install a translation of Heroes III in your preferred language - Nainstalujte si překlad Heroes III dle preferovaného jazyku + Nainstalujte si překlad Heroes III dle preferovaného jazyka From 9ef6696e785c68639aa9f389d1b78d5b3677593f Mon Sep 17 00:00:00 2001 From: George King <98261225+GeorgeK1ng@users.noreply.github.com> Date: Wed, 16 Oct 2024 23:54:41 +0200 Subject: [PATCH 67/69] Updated Czech translation Translated 2 overlooked lines --- Mods/vcmi/config/vcmi/czech.json | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Mods/vcmi/config/vcmi/czech.json b/Mods/vcmi/config/vcmi/czech.json index 9e72b3add..f0e0e0410 100644 --- a/Mods/vcmi/config/vcmi/czech.json +++ b/Mods/vcmi/config/vcmi/czech.json @@ -162,7 +162,7 @@ "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.dimensionDoor.seaToLandError" : "Pomocí dimenzní brány není možné se teleportovat z moře na pevninu nebo naopak.", "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.", @@ -253,7 +253,7 @@ "vcmi.adventureOptions.rightButtonDrag.hover" : "Přetahování pravým tlačítkem", "vcmi.adventureOptions.rightButtonDrag.help" : "{Přetahování pravým tlačítkem}\n\nKdyž je povoleno, pohyb myší se stisknutým pravým tlačítkem bude posouvat pohled na mapě dobrodružství.", "vcmi.adventureOptions.smoothDragging.hover" : "Plynulé posouvání mapy", - "vcmi.adventureOptions.smoothDragging.help" : "{Plynulé posouvání mapy}\n\nWhen enabled, map dragging has a modern run out effect.", // TODO + "vcmi.adventureOptions.smoothDragging.help" : "{Plynulé posouvání mapy}\n\nPokud je tato možnost aktivována, posouvání mapy bude plynulé.", "vcmi.adventureOptions.skipAdventureMapAnimations.hover" : "Přeskočit efekty mizení", "vcmi.adventureOptions.skipAdventureMapAnimations.help" : "{Přeskočit efekty mizení}\n\nKdyž je povoleno, přeskočí se efekty mizení objektů a podobné efekty (sběr surovin, nalodění atd.). V některých případech zrychlí uživatelské rozhraní na úkor estetiky. Obzvláště užitečné v PvP hrách. Pro maximální rychlost pohybu je toto nastavení aktivní bez ohledu na další volby.", "vcmi.adventureOptions.mapScrollSpeed1.hover": "", @@ -314,7 +314,7 @@ "vcmi.battleWindow.damageRetaliation.damage" : "(%DAMAGE).", "vcmi.battleWindow.damageRetaliation.damageKills" : "(%DAMAGE, %KILLS).", - "vcmi.battleWindow.killed" : "Zabito", //TODO + "vcmi.battleWindow.killed" : "Zabito", "vcmi.battleWindow.accurateShot.resultDescription.0" : "%d %s bylo zabito přesnými zásahy!", "vcmi.battleWindow.accurateShot.resultDescription.1" : "%d %s byl zabit přesným zásahem!", "vcmi.battleWindow.accurateShot.resultDescription.2" : "%d %s bylo zabito přesnými zásahy!", From 59dae43a74715451263eccdc87ae58872ee43b5e Mon Sep 17 00:00:00 2001 From: Laserlicht <13953785+Laserlicht@users.noreply.github.com> Date: Thu, 17 Oct 2024 02:12:41 +0200 Subject: [PATCH 68/69] fix remembering last map --- client/lobby/SelectionTab.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/lobby/SelectionTab.cpp b/client/lobby/SelectionTab.cpp index 2cf811129..8029dac48 100644 --- a/client/lobby/SelectionTab.cpp +++ b/client/lobby/SelectionTab.cpp @@ -693,7 +693,7 @@ void SelectionTab::selectFileName(std::string fname) for(int i = (int)allItems.size() - 1; i >= 0; i--) { - if(allItems[i]->fileURI == fname) + if(boost::to_upper_copy(allItems[i]->fileURI) == fname) { auto [folderName, baseFolder, parentExists, fileInFolder] = checkSubfolder(allItems[i]->originalFileURI); curFolder = baseFolder != "" ? baseFolder + "/" : ""; @@ -704,7 +704,7 @@ void SelectionTab::selectFileName(std::string fname) for(int i = (int)curItems.size() - 1; i >= 0; i--) { - if(curItems[i]->fileURI == fname) + if(boost::to_upper_copy(curItems[i]->fileURI) == fname) { slider->scrollTo(i); selectAbs(i); From 10332547ac59f76594e3a3dc943a76215528a07e Mon Sep 17 00:00:00 2001 From: George King <98261225+GeorgeK1ng@users.noreply.github.com> Date: Thu, 17 Oct 2024 09:42:46 +0200 Subject: [PATCH 69/69] Updated Czech translation --- mapeditor/translation/czech.ts | 138 ++++++++++++++++----------------- 1 file changed, 69 insertions(+), 69 deletions(-) diff --git a/mapeditor/translation/czech.ts b/mapeditor/translation/czech.ts index cfdc136c7..a7456cf42 100644 --- a/mapeditor/translation/czech.ts +++ b/mapeditor/translation/czech.ts @@ -67,22 +67,22 @@ Author - + Autor Author contact (e.g. email) - + Kontakt na autora (např. email) Map Creation Time - + Čas vytvoření mapy Map Version - + Verze mapy @@ -788,12 +788,12 @@ Set all mods having a game content as mandatory - + Nastavte všechny modifikace obsahující herní obsah jako povinné Full content mods - + Modifikace s kompletním herním obsahem @@ -836,7 +836,7 @@ Generate hero at main - + Vytvořit hrdinu v hlavním městě @@ -877,7 +877,7 @@ Portrait - + Portrét @@ -947,17 +947,17 @@ Can't place object - Nelze umístit objekt + Nelze umístit objekt There can only be one grail object on the map. - + Na mapě může být pouze jeden grál. Hero %1 cannot be created as NEUTRAL. - + Hrdina %1 nemůže být vytvořen jako NEUTRÁLNÍ. @@ -1129,7 +1129,7 @@ On select text - + Text při výběru @@ -1210,7 +1210,7 @@ Overflow - + Přetečení @@ -1473,37 +1473,37 @@ Build all - + Postavit vše Demolish all - + Zbořit vše Enable all - + Povolit vše Disable all - + Zakázat vše Type - Druh + Typ Enabled - + Povoleno Built - + Postaveno @@ -1511,77 +1511,77 @@ Town event - + Událost ve městě General - + Hlavní Event name - Název události + Název události Type event message text - Zadejte text zprávy události + Zadejte text události Day of first occurrence - Den prvního výskytu + Den prvního výskytu Repeat after (0 = no repeat) - Opakovat po (0 = bez opak.) + Opakovat po (0 = bez opakováí) Affected players - Ovlivnění hráči + Ovlivnění hráči affects human - ovlivňuje lidi + ovlivňuje lidi affects AI - ovlivňuje AI + ovlivňuje AI Resources - Zdroje + Zdroje Buildings - Budovy + Budovy Creatures - Jednotky + Jednotky OK - + OK Creature level %1 / Creature level %1 Upgrade - + Úroveň jednotky %1 / Úroveň jednotky%1 vylepšení Day %1 - %2 - + Den %1 - %2 @@ -1589,32 +1589,32 @@ Town events - + Události ve městě Timed events - Načasované události + Načasované události Add - Přidat + Přidat Remove - Odebrat + Odebrat Day %1 - %2 - + Den %1 - %2 New event - Nová událost + Nová událost @@ -1622,17 +1622,17 @@ Spells - Kouzla + Kouzla Customize spells - Přizpůsobit kouzla + Přizpůsobit kouzla Level 1 - Úroveň 1 + 1. stupeň @@ -1641,7 +1641,7 @@ Spell that may appear in mage guild - + Kouzlo, které se může objevit ve věži kouzel @@ -1650,27 +1650,27 @@ Spell that must appear in mage guild - + Kouzlo, které se musí objevit ve věži kouzel Level 2 - Úroveň 2 + 2. stupeň Level 3 - Úroveň 3 + 3. stupeň Level 4 - Úroveň 4 + 4. stupeň Level 5 - Úroveň 5 + 5. stupeň @@ -1722,7 +1722,7 @@ Map validation results - Výsledky posudku mapy + Výsledky ověření mapy @@ -1732,27 +1732,27 @@ No factions allowed for player %1 - + Pro hráče %1 nejsou povoleny žádné frakce No players allowed to play this map - Žádní hráči nejsou dovoleni hrát tuto mapu + Tato mapa neumožňuje hru žádnému hráči Map is allowed for one player and cannot be started - Mapa je pouze pro jednoho hráče na nemůže být spuštěna + Tato mapa je určena pouze pro jednoho hráče a nelze ji spustit No human players allowed to play this map - Žádní lidští hráči nejsou dovoleni hrát tuto mapu + Na této mapě není povolen žádný lidský hráč Armored instance %1 is UNFLAGGABLE but must have NEUTRAL or player owner - + Obrněná instance %1 nemůže být označena vlajkou, ale musí mít vlastníka nebo neutrálního nebo hráče @@ -1762,17 +1762,17 @@ Spell scroll %1 doesn't have instance assigned and must be removed - + Kouzelný svitek %1 nemá přiřazenou instanci a musí být odstraněn Artifact %1 is prohibited by map settings - + Artefakt %1 je zakázán nastavením mapy Player %1 has no towns and heroes assigned - + Hráč %1 nemá přiřazena žádná města ani hrdiny @@ -1797,7 +1797,7 @@ Hero %1 has an empty type and must be removed - + Hrdina %1 nemá přiřazený typ a musí být odstraněn @@ -1923,7 +1923,7 @@ Two level map - Dvě úrovně + Dvouvrstvá mapa @@ -2016,7 +2016,7 @@ Monster strength - Síla příšer + Síla jednotek @@ -2037,7 +2037,7 @@ Water content - Obsah vody + Vodní obsah @@ -2052,22 +2052,22 @@ Roads - Cesty + Cesty Dirt - + Hlína Gravel - + Štěrk Cobblestone - + Dlažba @@ -2115,7 +2115,7 @@ Filepath of the map to open. - Cesta k souboru mapy pro otevření. + Cesta k souboru mapy, kterou chcete otevřít. @@ -2135,7 +2135,7 @@ Delete original files, for the ones split / converted. - + Odstranit původní soubory pro ty, které byly rozděleny nebo převedeny.