diff --git a/AI/VCAI/Goals.cpp b/AI/VCAI/Goals.cpp index 4931e4e19..540e56e6c 100644 --- a/AI/VCAI/Goals.cpp +++ b/AI/VCAI/Goals.cpp @@ -275,7 +275,7 @@ TSubgoal Win::whatToDoToAchieve() // 0.85 -> radius now 2 tiles // 0.95 -> 1 tile radius, position is fully known // AFAIK H3 AI does something like this - int3 grailPos = cb->getGrailPos(ratio); + int3 grailPos = cb->getGrailPos(&ratio); if(ratio > 0.99) { return sptr (Goals::DigAtTile(grailPos)); diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index c8701f8dd..b982b14f2 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -2170,7 +2170,7 @@ void CPlayerInterface::showPuzzleMap() //TODO: interface should not know the real position of Grail... double ratio = 0; - int3 grailPos = cb->getGrailPos(ratio); + int3 grailPos = cb->getGrailPos(&ratio); GH.pushInt(new CPuzzleWindow(grailPos, ratio)); } diff --git a/client/Client.cpp b/client/Client.cpp index 92b03d2a2..66e01b7ef 100644 --- a/client/Client.cpp +++ b/client/Client.cpp @@ -219,18 +219,20 @@ void CClient::endGame( bool closeConnection /*= true*/ ) GH.curInt = nullptr; { boost::unique_lock un(*LOCPLINT->pim); - logNetwork->infoStream() << "Ending current game!"; + logNetwork->infoStream() << "Ending current game!"; if(GH.topInt()) + { GH.topInt()->deactivate(); + } GH.listInt.clear(); GH.objsToBlit.clear(); GH.statusbar = nullptr; - logNetwork->infoStream() << "Removed GUI."; + logNetwork->infoStream() << "Removed GUI."; vstd::clear_pointer(const_cast(CGI)->mh); vstd::clear_pointer(gs); - logNetwork->infoStream() << "Deleted mapHandler and gameState."; + logNetwork->infoStream() << "Deleted mapHandler and gameState."; LOCPLINT = nullptr; } @@ -238,9 +240,9 @@ void CClient::endGame( bool closeConnection /*= true*/ ) battleints.clear(); callbacks.clear(); battleCallbacks.clear(); - logNetwork->infoStream() << "Deleted playerInts."; - - logNetwork->infoStream() << "Client stopped."; + CGObelisk::reset(); + logNetwork->infoStream() << "Deleted playerInts."; + logNetwork->infoStream() << "Client stopped."; } #if 1 diff --git a/lib/CGameInfoCallback.cpp b/lib/CGameInfoCallback.cpp index 08af6db42..0d9f4e868 100644 --- a/lib/CGameInfoCallback.cpp +++ b/lib/CGameInfoCallback.cpp @@ -727,15 +727,16 @@ int CPlayerSpecificInfoCallback::getHeroSerial(const CGHeroInstance * hero, bool return -1; } -int3 CPlayerSpecificInfoCallback::getGrailPos( double &outKnownRatio ) +int3 CPlayerSpecificInfoCallback::getGrailPos( double *outKnownRatio ) { if (!player || CGObelisk::obeliskCount == 0) { - outKnownRatio = 0.0; + *outKnownRatio = 0.0; } else { - outKnownRatio = static_cast(CGObelisk::visited[gs->getPlayerTeam(*player)->id]) / CGObelisk::obeliskCount; + *outKnownRatio = static_cast(CGObelisk::visited[gs->getPlayerTeam(*player)->id]) + / CGObelisk::obeliskCount; } return gs->map->grailPos; } diff --git a/lib/CGameInfoCallback.h b/lib/CGameInfoCallback.h index 81c691e71..4d2903657 100644 --- a/lib/CGameInfoCallback.h +++ b/lib/CGameInfoCallback.h @@ -125,7 +125,7 @@ class DLL_LINKAGE CPlayerSpecificInfoCallback : public CGameInfoCallback public: int howManyTowns() const; int howManyHeroes(bool includeGarrisoned = true) const; - int3 getGrailPos(double &outKnownRatio); + int3 getGrailPos(double *outKnownRatio); boost::optional getMyColor() const; std::vector getTownsInfo(bool onlyOur = true) const; //true -> only owned; false -> all visible @@ -139,7 +139,7 @@ public: int getResourceAmount(Res::ERes type) const; TResources getResourceAmount() const; - const std::vector< std::vector< std::vector > > & getVisibilityMap()const; //returns visibility map + const std::vector< std::vector< std::vector > > & getVisibilityMap()const; //returns visibility map const PlayerSettings * getPlayerSettings(PlayerColor color) const; }; @@ -154,4 +154,3 @@ public: virtual void showInfoDialog(const std::string &msg, PlayerColor player); }; - diff --git a/lib/CModHandler.cpp b/lib/CModHandler.cpp index b2a523168..85fcdb924 100644 --- a/lib/CModHandler.cpp +++ b/lib/CModHandler.cpp @@ -554,7 +554,7 @@ void CModHandler::loadConfigFromFile (std::string name) std::string paths; for(auto& p : CResourceHandler::get()->getResourceNames(ResourceID("config/" + name))) { - paths += p + ", "; + paths += p.string() + ", "; } paths = paths.substr(0, paths.size() - 2); logGlobal->debugStream() << "Loading hardcoded features settings from [" << paths << "], result:"; diff --git a/lib/Connection.h b/lib/Connection.h index 5e3ee07a9..69e3725b4 100644 --- a/lib/Connection.h +++ b/lib/Connection.h @@ -27,7 +27,7 @@ #include "mapping/CCampaignHandler.h" //for CCampaignState #include "rmg/CMapGenerator.h" // for CMapGenOptions -const ui32 version = 756; +const ui32 version = 757; const ui32 minSupportedVersion = 753; class CISer; diff --git a/lib/filesystem/AdapterLoaders.cpp b/lib/filesystem/AdapterLoaders.cpp index e7483fa66..5033fe919 100644 --- a/lib/filesystem/AdapterLoaders.cpp +++ b/lib/filesystem/AdapterLoaders.cpp @@ -87,9 +87,9 @@ boost::optional CFilesystemList::getResourceName(const return boost::optional(); } -std::set CFilesystemList::getResourceNames(const ResourceID & resourceName) const +std::set CFilesystemList::getResourceNames(const ResourceID & resourceName) const { - std::set paths; + std::set paths; for(auto& loader : getResourcesWithName(resourceName)) { auto rn = loader->getResourceName(resourceName); diff --git a/lib/filesystem/AdapterLoaders.h b/lib/filesystem/AdapterLoaders.h index 51f9ce789..6b2db0592 100644 --- a/lib/filesystem/AdapterLoaders.h +++ b/lib/filesystem/AdapterLoaders.h @@ -1,87 +1,87 @@ -#pragma once - -/* - * AdapterLoaders.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 - * - */ - -#include "ISimpleResourceLoader.h" -#include "ResourceID.h" - -class CFileInfo; -class CInputStream; -class JsonNode; - -/** - * Class that implements file mapping (aka *nix symbolic links) - * Uses json file as input, content is map: - * "fileA.txt" : "fileB.txt" - * Note that extension is necessary, but used only to determine type - * - * fileA - file which will be replaced - * fileB - file which will be used as replacement - */ -class DLL_LINKAGE CMappedFileLoader : public ISimpleResourceLoader -{ -public: - /** - * Ctor. - * - * @param config Specifies filesystem configuration - */ - explicit CMappedFileLoader(const std::string &mountPoint, const JsonNode & config); - - /// Interface implementation - /// @see ISimpleResourceLoader - std::unique_ptr load(const ResourceID & resourceName) const override; - bool existsResource(const ResourceID & resourceName) const override; - std::string getMountPoint() const override; - boost::optional getResourceName(const ResourceID & resourceName) const override; - std::unordered_set getFilteredFiles(std::function filter) const override; - -private: - /** A list of files in this map - * key = ResourceID for resource loader - * value = ResourceID to which file this request will be redirected - */ - std::unordered_map fileList; -}; - -class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader -{ - std::vector > loaders; - - std::set writeableLoaders; - - //FIXME: this is only compile fix, should be removed in the end - CFilesystemList(CFilesystemList &) = delete; - CFilesystemList &operator=(CFilesystemList &) = delete; +#pragma once -public: - CFilesystemList(); - ~CFilesystemList(); - /// Interface implementation - /// @see ISimpleResourceLoader - std::unique_ptr load(const ResourceID & resourceName) const override; - bool existsResource(const ResourceID & resourceName) const override; - std::string getMountPoint() const override; - boost::optional getResourceName(const ResourceID & resourceName) const override; - std::set getResourceNames(const ResourceID & resourceName) const override; - std::unordered_set getFilteredFiles(std::function filter) const override; - bool createResource(std::string filename, bool update = false) override; - std::vector getResourcesWithName(const ResourceID & resourceName) const override; - - /** - * Adds a resource loader to the loaders list - * Passes loader ownership to this object - * - * @param loader The simple resource loader object to add - * @param writeable - resource shall be treated as writeable - */ - void addLoader(ISimpleResourceLoader * loader, bool writeable); -}; +/* + * AdapterLoaders.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 + * + */ + +#include "ISimpleResourceLoader.h" +#include "ResourceID.h" + +class CFileInfo; +class CInputStream; +class JsonNode; + +/** + * Class that implements file mapping (aka *nix symbolic links) + * Uses json file as input, content is map: + * "fileA.txt" : "fileB.txt" + * Note that extension is necessary, but used only to determine type + * + * fileA - file which will be replaced + * fileB - file which will be used as replacement + */ +class DLL_LINKAGE CMappedFileLoader : public ISimpleResourceLoader +{ +public: + /** + * Ctor. + * + * @param config Specifies filesystem configuration + */ + explicit CMappedFileLoader(const std::string &mountPoint, const JsonNode & config); + + /// Interface implementation + /// @see ISimpleResourceLoader + std::unique_ptr load(const ResourceID & resourceName) const override; + bool existsResource(const ResourceID & resourceName) const override; + std::string getMountPoint() const override; + boost::optional getResourceName(const ResourceID & resourceName) const override; + std::unordered_set getFilteredFiles(std::function filter) const override; + +private: + /** A list of files in this map + * key = ResourceID for resource loader + * value = ResourceID to which file this request will be redirected + */ + std::unordered_map fileList; +}; + +class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader +{ + std::vector > loaders; + + std::set writeableLoaders; + + //FIXME: this is only compile fix, should be removed in the end + CFilesystemList(CFilesystemList &) = delete; + CFilesystemList &operator=(CFilesystemList &) = delete; + +public: + CFilesystemList(); + ~CFilesystemList(); + /// Interface implementation + /// @see ISimpleResourceLoader + std::unique_ptr load(const ResourceID & resourceName) const override; + bool existsResource(const ResourceID & resourceName) const override; + std::string getMountPoint() const override; + boost::optional getResourceName(const ResourceID & resourceName) const override; + std::set getResourceNames(const ResourceID & resourceName) const override; + std::unordered_set getFilteredFiles(std::function filter) const override; + bool createResource(std::string filename, bool update = false) override; + std::vector getResourcesWithName(const ResourceID & resourceName) const override; + + /** + * Adds a resource loader to the loaders list + * Passes loader ownership to this object + * + * @param loader The simple resource loader object to add + * @param writeable - resource shall be treated as writeable + */ + void addLoader(ISimpleResourceLoader * loader, bool writeable); +}; diff --git a/lib/filesystem/ISimpleResourceLoader.h b/lib/filesystem/ISimpleResourceLoader.h index d3b78e353..a4c969883 100644 --- a/lib/filesystem/ISimpleResourceLoader.h +++ b/lib/filesystem/ISimpleResourceLoader.h @@ -58,9 +58,9 @@ public: * * @return std::set with names. */ - virtual std::set getResourceNames(const ResourceID & resourceName) const + virtual std::set getResourceNames(const ResourceID & resourceName) const { - std::set result; + std::set result; auto rn = getResourceName(resourceName); if(rn) { diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 0db3258bd..1ffe5fda0 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -416,6 +416,7 @@ void CGSeerHut::init() { seerName = *RandomGeneratorUtil::nextItem(VLC->generaltexth->seerNames, cb->gameState()->getRandomGenerator()); quest->textOption = cb->gameState()->getRandomGenerator().nextInt(2); + quest->completedOption = cb->gameState()->getRandomGenerator().nextInt(1, 5); } void CGSeerHut::initObj() @@ -435,7 +436,7 @@ void CGSeerHut::initObj() else { quest->progress = CQuest::COMPLETE; - quest->firstVisitText = VLC->generaltexth->seerEmpty[quest->textOption]; + quest->firstVisitText = VLC->generaltexth->seerEmpty[quest->completedOption]; } } @@ -533,7 +534,7 @@ void CGSeerHut::newTurn() const { if (quest->lastDay >= 0 && quest->lastDay < cb->getDate()-1) //time is up { - cb->setObjProperty (id, 10, CQuest::COMPLETE); + cb->setObjProperty (id, CGSeerHut::OBJPROP_VISITED, CQuest::COMPLETE); } } @@ -550,7 +551,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const if (firstVisit) { isCustom = quest->isCustomFirst; - cb->setObjProperty (id, 10, CQuest::IN_PROGRESS); + cb->setObjProperty (id, CGSeerHut::OBJPROP_VISITED, CQuest::IN_PROGRESS); AddQuest aq; aq.quest = QuestInfo (quest, this, visitablePos()); @@ -582,7 +583,7 @@ void CGSeerHut::onHeroVisit( const CGHeroInstance * h ) const } else { - iw.text << VLC->generaltexth->seerEmpty[quest->textOption]; + iw.text << VLC->generaltexth->seerEmpty[quest->completedOption]; if (ID == Obj::SEER_HUT) iw.text.addReplacement(seerName); cb->showInfoDialog(&iw); @@ -657,7 +658,7 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const default: break; } - cb->setObjProperty (id, 10, CQuest::COMPLETE); //mission complete + cb->setObjProperty (id, CGSeerHut::OBJPROP_VISITED, CQuest::COMPLETE); //mission complete completeQuest(h); //make sure to remove QuestGuard at the very end } } diff --git a/lib/mapObjects/CQuest.h b/lib/mapObjects/CQuest.h index cc9fd9063..63eb998d3 100644 --- a/lib/mapObjects/CQuest.h +++ b/lib/mapObjects/CQuest.h @@ -37,8 +37,11 @@ public: std::vector m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant std::vector m7resources; //TODO: use resourceset? - //following field are used only for kill creature/hero missions, the original objects became inaccessible after their removal, so we need to store info needed for messages / hover text + // following fields are used only for kill creature/hero missions, the original + // objects became inaccessible after their removal, so we need to store info + // needed for messages / hover text ui8 textOption; + ui8 completedOption; CStackBasicDescriptor stackToKill; ui8 stackDirection; std::string heroName; //backup of hero name @@ -66,7 +69,16 @@ public: { h & qid & missionType & progress & lastDay & m13489val & m2stats & m5arts & m6creatures & m7resources & textOption & stackToKill & stackDirection & heroName & heroPortrait - & firstVisitText & nextVisitText & completedText & isCustomFirst & isCustomNext & isCustomComplete; + & firstVisitText & nextVisitText & completedText & isCustomFirst + & isCustomNext & isCustomComplete; + if(version >= 757) + { + h & completedOption; + } + else if(!h.saving) + { + completedOption = 1; + } } }; @@ -118,6 +130,8 @@ public: h & rewardType & rID & rVal & seerName; } protected: + static constexpr int OBJPROP_VISITED = 10; + void setPropertyDer(ui8 what, ui32 val) override; }; diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 5f1014670..0cada5240 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -24,7 +24,7 @@ #include "../CPlayerState.h" std::map > CGMagi::eyelist; -ui8 CGObelisk::obeliskCount; //how many obelisks are on map +ui8 CGObelisk::obeliskCount = 0; //how many obelisks are on map std::map CGObelisk::visited; //map: team_id => how many obelisks has been visited ///helpers @@ -60,7 +60,7 @@ static std::string & visitedTxt(const bool visited) void CPlayersVisited::setPropertyDer( ui8 what, ui32 val ) { - if(what == 10) + if(what == CPlayersVisited::OBJPROP_VISITED) players.insert(PlayerColor(val)); } @@ -1314,7 +1314,7 @@ void CGWitchHut::onHeroVisit( const CGHeroInstance * h ) const iw.soundID = soundBase::gazebo; iw.player = h->getOwner(); if(!wasVisited(h->tempOwner)) - cb->setObjProperty(id, 10, h->tempOwner.getNum()); + cb->setObjProperty(id, CGWitchHut::OBJPROP_VISITED, h->tempOwner.getNum()); ui32 txt_id; if(h->getSecSkillLevel(SecondarySkill(ability))) //you already know this skill { @@ -1424,7 +1424,7 @@ void CGShrine::onHeroVisit( const CGHeroInstance * h ) const } if(!wasVisited(h->tempOwner)) - cb->setObjProperty(id, 10, h->tempOwner.getNum()); + cb->setObjProperty(id, CGShrine::OBJPROP_VISITED, h->tempOwner.getNum()); InfoWindow iw; iw.soundID = soundBase::temple; @@ -1826,7 +1826,7 @@ void CCartographer::blockingDialogAnswered(const CGHeroInstance *hero, ui32 answ //water = 0; land = 1; underground = 2; cb->getAllTiles (fw.tiles, hero->tempOwner, subID - 1, !subID + 1); //reveal appropriate tiles cb->sendAndApply (&fw); - cb->setObjProperty (id, 10, hero->tempOwner.getNum()); + cb->setObjProperty (id, CCartographer::OBJPROP_VISITED, hero->tempOwner.getNum()); } } @@ -1848,11 +1848,16 @@ void CGObelisk::onHeroVisit( const CGHeroInstance * h ) const iw.text.addTxt(MetaString::ADVOB_TXT, 96); cb->sendAndApply(&iw); - cb->setObjProperty(id, 20, h->tempOwner.getNum()); //increment general visited obelisks counter + // increment general visited obelisks counter + cb->setObjProperty(id, CGObelisk::OBJPROP_INC, team.getNum()); openWindow(OpenWindow::PUZZLE_MAP, h->tempOwner.getNum()); - cb->setObjProperty(id, 10, h->tempOwner.getNum()); //mark that particular obelisk as visited + // mark that particular obelisk as visited for all players in the team + for (auto & color : ts->players) + { + cb->setObjProperty(id, CGObelisk::OBJPROP_VISITED, color.getNum()); + } } else { @@ -1867,6 +1872,12 @@ void CGObelisk::initObj() obeliskCount++; } +void CGObelisk::reset() +{ + obeliskCount = 0; + visited.clear(); +} + std::string CGObelisk::getHoverText(PlayerColor player) const { return getObjectName() + " " + visitedTxt(wasVisited(player)); @@ -1874,20 +1885,26 @@ std::string CGObelisk::getHoverText(PlayerColor player) const void CGObelisk::setPropertyDer( ui8 what, ui32 val ) { - CPlayersVisited::setPropertyDer(what, val); switch(what) { - case 20: - assert(val < PlayerColor::PLAYER_LIMIT_I); - visited[TeamID(val)]++; + case CGObelisk::OBJPROP_INC: + { + assert(val < PlayerColor::PLAYER_LIMIT_I); + auto progress = ++visited[TeamID(val)]; + logGlobal->debugStream() << boost::format("Player %d: obelisk progress %d / %d") + % val % static_cast(progress) % static_cast(obeliskCount); - if(visited[TeamID(val)] > obeliskCount) - { - logGlobal->errorStream() << "Error: Visited " << visited[TeamID(val)] << "\t\t" << obeliskCount; - assert(0); - } + if(progress > obeliskCount) + { + logGlobal->errorStream() << "Error: Visited " << progress << "\t\t" << obeliskCount; + assert(0); + } - break; + break; + } + default: + CPlayersVisited::setPropertyDer(what, val); + break; } } diff --git a/lib/mapObjects/MiscObjects.h b/lib/mapObjects/MiscObjects.h index aa3afe4c6..5cc9f379f 100644 --- a/lib/mapObjects/MiscObjects.h +++ b/lib/mapObjects/MiscObjects.h @@ -28,6 +28,8 @@ public: h & static_cast(*this); h & players; } + + static constexpr int OBJPROP_VISITED = 10; }; class DLL_LINKAGE CGCreature : public CArmedInstance //creatures on map @@ -451,12 +453,14 @@ class DLL_LINKAGE CGDenOfthieves : public CGObjectInstance class DLL_LINKAGE CGObelisk : public CPlayersVisited { public: + static constexpr int OBJPROP_INC = 20; static ui8 obeliskCount; //how many obelisks are on map static std::map visited; //map: team_id => how many obelisks has been visited void onHeroVisit(const CGHeroInstance * h) const override; void initObj() override; std::string getHoverText(PlayerColor player) const override; + static void reset(); template void serialize(Handler &h, const int version) {