فهرست منبع

Merge branch 'develop' of https://github.com/vcmi/vcmi into develop

DjWarmonger 9 سال پیش
والد
کامیت
fdfe7b6b06

+ 1 - 1
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));

+ 1 - 1
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));
 }

+ 8 - 6
client/Client.cpp

@@ -219,18 +219,20 @@ void CClient::endGame( bool closeConnection /*= true*/ )
 	GH.curInt = nullptr;
 	{
 		boost::unique_lock<boost::recursive_mutex> 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<CGameInfo*>(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

+ 4 - 3
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<double>(CGObelisk::visited[gs->getPlayerTeam(*player)->id]) / CGObelisk::obeliskCount;
+		*outKnownRatio = static_cast<double>(CGObelisk::visited[gs->getPlayerTeam(*player)->id])
+			/ CGObelisk::obeliskCount;
 	}
 	return gs->map->grailPos;
 }

+ 2 - 3
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<PlayerColor> getMyColor() const;
 
 	std::vector <const CGTownInstance *> 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<ui8> > > & getVisibilityMap()const; //returns visibility map 
+	const std::vector< std::vector< std::vector<ui8> > > & 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);
 };
-

+ 1 - 1
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:";

+ 1 - 1
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;

+ 2 - 2
lib/filesystem/AdapterLoaders.cpp

@@ -87,9 +87,9 @@ boost::optional<boost::filesystem::path> CFilesystemList::getResourceName(const
 	return boost::optional<boost::filesystem::path>();
 }
 
-std::set<std::string> CFilesystemList::getResourceNames(const ResourceID & resourceName) const
+std::set<boost::filesystem::path> CFilesystemList::getResourceNames(const ResourceID & resourceName) const
 {
-	std::set<std::string> paths;
+	std::set<boost::filesystem::path> paths;
 	for(auto& loader : getResourcesWithName(resourceName))
 	{
 		auto rn = loader->getResourceName(resourceName);

+ 86 - 86
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<CInputStream> load(const ResourceID & resourceName) const override;
-	bool existsResource(const ResourceID & resourceName) const override;
-	std::string getMountPoint() const override;
-	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
-	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> 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<ResourceID, ResourceID> fileList;
-};
-
-class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader
-{
-	std::vector<std::unique_ptr<ISimpleResourceLoader> > loaders;
-
-	std::set<ISimpleResourceLoader *> 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<CInputStream> load(const ResourceID & resourceName) const override;
-	bool existsResource(const ResourceID & resourceName) const override;
-	std::string getMountPoint() const override;
-	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
-	std::set<std::string> getResourceNames(const ResourceID & resourceName) const override;
-	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
-	bool createResource(std::string filename, bool update = false) override;
-	std::vector<const ISimpleResourceLoader *> 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<CInputStream> load(const ResourceID & resourceName) const override;
+	bool existsResource(const ResourceID & resourceName) const override;
+	std::string getMountPoint() const override;
+	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
+	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> 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<ResourceID, ResourceID> fileList;
+};
+
+class DLL_LINKAGE CFilesystemList : public ISimpleResourceLoader
+{
+	std::vector<std::unique_ptr<ISimpleResourceLoader> > loaders;
+
+	std::set<ISimpleResourceLoader *> 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<CInputStream> load(const ResourceID & resourceName) const override;
+	bool existsResource(const ResourceID & resourceName) const override;
+	std::string getMountPoint() const override;
+	boost::optional<boost::filesystem::path> getResourceName(const ResourceID & resourceName) const override;
+	std::set<boost::filesystem::path> getResourceNames(const ResourceID & resourceName) const override;
+	std::unordered_set<ResourceID> getFilteredFiles(std::function<bool(const ResourceID &)> filter) const override;
+	bool createResource(std::string filename, bool update = false) override;
+	std::vector<const ISimpleResourceLoader *> 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);
+};

+ 2 - 2
lib/filesystem/ISimpleResourceLoader.h

@@ -58,9 +58,9 @@ public:
 	 *
 	 * @return std::set with names.
 	 */
-	virtual std::set<std::string> getResourceNames(const ResourceID & resourceName) const
+	virtual std::set<boost::filesystem::path> getResourceNames(const ResourceID & resourceName) const
 	{
-		std::set<std::string> result;
+		std::set<boost::filesystem::path> result;
 		auto rn = getResourceName(resourceName);
 		if(rn)
 		{

+ 6 - 5
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
 	}
 }

+ 16 - 2
lib/mapObjects/CQuest.h

@@ -37,8 +37,11 @@ public:
 	std::vector<CStackBasicDescriptor> m6creatures; //pair[cre id, cre count], CreatureSet info irrelevant
 	std::vector<ui32> 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;
 };
 

+ 34 - 17
lib/mapObjects/MiscObjects.cpp

@@ -24,7 +24,7 @@
 #include "../CPlayerState.h"
 
 std::map <si32, std::vector<ObjectInstanceID> > CGMagi::eyelist;
-ui8 CGObelisk::obeliskCount; //how many obelisks are on map
+ui8 CGObelisk::obeliskCount = 0; //how many obelisks are on map
 std::map<TeamID, ui8> 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<int>(progress) % static_cast<int>(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;
 	}
 }
 

+ 4 - 0
lib/mapObjects/MiscObjects.h

@@ -28,6 +28,8 @@ public:
 		h & static_cast<CGObjectInstance&>(*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<TeamID, ui8> 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 <typename Handler> void serialize(Handler &h, const int version)
 	{