Browse Source

Merge pull request #5942 from IvanSavenko/university_popup

Show skill that can be learned in university on right click
Ivan Savenko 2 months ago
parent
commit
b7521450fb

+ 1 - 1
client/widgets/CComponent.cpp

@@ -119,7 +119,7 @@ std::vector<AnimationPath> CComponent::getFileName() const
 	static const std::array<std::string, 4>  primSkillsArr = {"PSKIL32",        "PSKIL32",        "PSKIL42",        "PSKILL"};
 	static const std::array<std::string, 4>  primSkillsArr = {"PSKIL32",        "PSKIL32",        "PSKIL42",        "PSKILL"};
 	static const std::array<std::string, 4>  secSkillsArr =  {"SECSK32",        "SECSK32",        "SECSKILL",       "SECSK82"};
 	static const std::array<std::string, 4>  secSkillsArr =  {"SECSK32",        "SECSK32",        "SECSKILL",       "SECSK82"};
 	static const std::array<std::string, 4>  resourceArr =   {"SMALRES",        "RESOURCE",       "RESOURCE",       "RESOUR82"};
 	static const std::array<std::string, 4>  resourceArr =   {"SMALRES",        "RESOURCE",       "RESOURCE",       "RESOUR82"};
-	static const std::array<std::string, 4>  creatureArr =   {"CPRSMALL",       "CPRSMALL",       "CPRSMALL",       "TWCRPORT"};
+	static const std::array<std::string, 4>  creatureArr =   {"CPRSMALL",       "CPRSMALL",       "TWCRPORT",       "TWCRPORT"};
 	static const std::array<std::string, 4>  artifactArr =   {"Artifact",       "Artifact",       "Artifact",       "Artifact"};
 	static const std::array<std::string, 4>  artifactArr =   {"Artifact",       "Artifact",       "Artifact",       "Artifact"};
 	static const std::array<std::string, 4>  spellsArr =     {"SpellInt",       "SpellInt",       "SpellInt",       "SPELLSCR"};
 	static const std::array<std::string, 4>  spellsArr =     {"SpellInt",       "SpellInt",       "SpellInt",       "SPELLSCR"};
 	static const std::array<std::string, 4>  moraleArr =     {"IMRL22",         "IMRL30",         "IMRL42",         "imrl82"};
 	static const std::array<std::string, 4>  moraleArr =     {"IMRL22",         "IMRL30",         "IMRL42",         "imrl82"};

+ 1 - 0
client/windows/GUIClasses.cpp

@@ -51,6 +51,7 @@
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/mapObjects/CGMarket.h"
 #include "../lib/mapObjects/CGMarket.h"
 #include "../lib/mapObjects/CGTownInstance.h"
 #include "../lib/mapObjects/CGTownInstance.h"
+#include "../lib/mapObjects/ObjectTemplate.h"
 #include "../lib/gameState/CGameState.h"
 #include "../lib/gameState/CGameState.h"
 #include "../lib/gameState/SThievesGuildInfo.h"
 #include "../lib/gameState/SThievesGuildInfo.h"
 #include "../lib/gameState/TavernHeroesPool.h"
 #include "../lib/gameState/TavernHeroesPool.h"

+ 1 - 1
client/windows/InfoWindows.cpp

@@ -233,7 +233,7 @@ void CRClickPopup::createAndPush(const CGObjectInstance * obj, const Point & p,
 
 
 		std::vector<std::shared_ptr<CComponent>> guiComponents;
 		std::vector<std::shared_ptr<CComponent>> guiComponents;
 		for(auto & component : components)
 		for(auto & component : components)
-			guiComponents.push_back(std::make_shared<CComponent>(component));
+			guiComponents.push_back(std::make_shared<CComponent>(component, CComponent::medium));
 
 
 		if(GAME->interface()->localState->getCurrentHero())
 		if(GAME->interface()->localState->getCurrentHero())
 			CRClickPopup::createAndPush(obj->getPopupText(GAME->interface()->localState->getCurrentHero()), guiComponents);
 			CRClickPopup::createAndPush(obj->getPopupText(GAME->interface()->localState->getCurrentHero()), guiComponents);

+ 2 - 1
config/objects/markets.json

@@ -124,6 +124,7 @@
 					"rarity"	: 20
 					"rarity"	: 20
 				},
 				},
 				"modes" : ["resource-skill"],
 				"modes" : ["resource-skill"],
+				"description" : "@core.xtrainfo.24",
 				"speech" : "@core.genrltxt.603",
 				"speech" : "@core.genrltxt.603",
 				"offer": 
 				"offer": 
 				[
 				[
@@ -135,4 +136,4 @@
 			}
 			}
 		}
 		}
 	}
 	}
-}
+}

+ 2 - 0
lib/CMakeLists.txt

@@ -140,6 +140,7 @@ set(lib_MAIN_SRCS
 	mapObjectConstructors/DwellingInstanceConstructor.cpp
 	mapObjectConstructors/DwellingInstanceConstructor.cpp
 	mapObjectConstructors/FlaggableInstanceConstructor.cpp
 	mapObjectConstructors/FlaggableInstanceConstructor.cpp
 	mapObjectConstructors/HillFortInstanceConstructor.cpp
 	mapObjectConstructors/HillFortInstanceConstructor.cpp
+	mapObjectConstructors/MarketInstanceConstructor.cpp
 	mapObjectConstructors/ShipyardInstanceConstructor.cpp
 	mapObjectConstructors/ShipyardInstanceConstructor.cpp
 
 
 	mapObjects/CGCreature.cpp
 	mapObjects/CGCreature.cpp
@@ -565,6 +566,7 @@ set(lib_MAIN_HEADERS
 	mapObjectConstructors/HillFortInstanceConstructor.h
 	mapObjectConstructors/HillFortInstanceConstructor.h
 	mapObjectConstructors/FlaggableInstanceConstructor.h
 	mapObjectConstructors/FlaggableInstanceConstructor.h
 	mapObjectConstructors/IObjectInfo.h
 	mapObjectConstructors/IObjectInfo.h
+	mapObjectConstructors/MarketInstanceConstructor.h
 	mapObjectConstructors/RandomMapInfo.h
 	mapObjectConstructors/RandomMapInfo.h
 	mapObjectConstructors/ShipyardInstanceConstructor.h
 	mapObjectConstructors/ShipyardInstanceConstructor.h
 	mapObjectConstructors/SObjectSounds.h
 	mapObjectConstructors/SObjectSounds.h

+ 1 - 0
lib/mapObjectConstructors/CObjectClassesHandler.cpp

@@ -25,6 +25,7 @@
 #include "../mapObjectConstructors/DwellingInstanceConstructor.h"
 #include "../mapObjectConstructors/DwellingInstanceConstructor.h"
 #include "../mapObjectConstructors/FlaggableInstanceConstructor.h"
 #include "../mapObjectConstructors/FlaggableInstanceConstructor.h"
 #include "../mapObjectConstructors/HillFortInstanceConstructor.h"
 #include "../mapObjectConstructors/HillFortInstanceConstructor.h"
+#include "../mapObjectConstructors/MarketInstanceConstructor.h"
 #include "../mapObjectConstructors/ShipyardInstanceConstructor.h"
 #include "../mapObjectConstructors/ShipyardInstanceConstructor.h"
 
 
 #include "../mapObjects/CGCreature.h"
 #include "../mapObjects/CGCreature.h"

+ 1 - 91
lib/mapObjectConstructors/CommonConstructors.cpp

@@ -10,24 +10,20 @@
 #include "StdInc.h"
 #include "StdInc.h"
 #include "CommonConstructors.h"
 #include "CommonConstructors.h"
 
 
-#include "../texts/CGeneralTextHandler.h"
 #include "../json/JsonRandom.h"
 #include "../json/JsonRandom.h"
 #include "../constants/StringConstants.h"
 #include "../constants/StringConstants.h"
-#include "../TerrainHandler.h"
 #include "../GameLibrary.h"
 #include "../GameLibrary.h"
 
 
-#include "../CConfigHandler.h"
 #include "../callback/IGameInfoCallback.h"
 #include "../callback/IGameInfoCallback.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/faction/CTownHandler.h"
 #include "../entities/hero/CHeroClass.h"
 #include "../entities/hero/CHeroClass.h"
-#include "../json/JsonUtils.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../mapObjects/CGHeroInstance.h"
-#include "../mapObjects/CGMarket.h"
 #include "../mapObjects/CGTownInstance.h"
 #include "../mapObjects/CGTownInstance.h"
 #include "../mapObjects/MiscObjects.h"
 #include "../mapObjects/MiscObjects.h"
 #include "../mapObjects/ObjectTemplate.h"
 #include "../mapObjects/ObjectTemplate.h"
 #include "../mapping/TerrainTile.h"
 #include "../mapping/TerrainTile.h"
 #include "../modding/IdentifierStorage.h"
 #include "../modding/IdentifierStorage.h"
+#include "../texts/TextIdentifier.h"
 
 
 VCMI_LIB_NAMESPACE_BEGIN
 VCMI_LIB_NAMESPACE_BEGIN
 
 
@@ -277,90 +273,4 @@ AnimationPath BoatInstanceConstructor::getBoatAnimationName() const
 	return actualAnimation;
 	return actualAnimation;
 }
 }
 
 
-void MarketInstanceConstructor::initTypeData(const JsonNode & input)
-{
-	if (settings["mods"]["validation"].String() != "off")
-		JsonUtils::validate(input, "vcmi:market", getJsonKey());
-
-	if (!input["description"].isNull())
-	{
-		std::string description = input["description"].String();
-		descriptionTextID = TextIdentifier(getBaseTextID(), "description").get();
-		LIBRARY->generaltexth->registerString( input.getModScope(), descriptionTextID, input["description"]);
-	}
-
-	if (!input["speech"].isNull())
-	{
-		std::string speech = input["speech"].String();
-		if (!speech.empty() && speech.at(0) == '@')
-		{
-			speechTextID = speech.substr(1);
-		}
-		else
-		{
-			speechTextID = TextIdentifier(getBaseTextID(), "speech").get();
-			LIBRARY->generaltexth->registerString( input.getModScope(), speechTextID, input["speech"]);
-		}
-	}
-
-	for(auto & element : input["modes"].Vector())
-	{
-		if(MappedKeys::MARKET_NAMES_TO_TYPES.count(element.String()))
-			marketModes.insert(MappedKeys::MARKET_NAMES_TO_TYPES.at(element.String()));
-	}
-	
-	marketEfficiency = input["efficiency"].isNull() ? 5 : input["efficiency"].Integer();
-	predefinedOffer = input["offer"];
-}
-
-bool MarketInstanceConstructor::hasDescription() const
-{
-	return !descriptionTextID.empty();
-}
-
-std::shared_ptr<CGMarket> MarketInstanceConstructor::createObject(IGameInfoCallback * cb) const
-{
-	if(marketModes.size() == 1)
-	{
-		switch(*marketModes.begin())
-		{
-			case EMarketMode::ARTIFACT_RESOURCE:
-			case EMarketMode::RESOURCE_ARTIFACT:
-				return std::make_shared<CGBlackMarket>(cb);
-
-			case EMarketMode::RESOURCE_SKILL:
-				return std::make_shared<CGUniversity>(cb);
-		}
-	}
-	return std::make_shared<CGMarket>(cb);
-}
-
-const std::set<EMarketMode> & MarketInstanceConstructor::availableModes() const
-{
-	return marketModes;
-}
-
-void MarketInstanceConstructor::randomizeObject(CGMarket * object, IGameRandomizer & gameRandomizer) const
-{
-	JsonRandom randomizer(object->cb, gameRandomizer);
-	JsonRandom::Variables emptyVariables;
-
-	if(auto * university = dynamic_cast<CGUniversity *>(object))
-	{
-		for(auto skill : randomizer.loadSecondaries(predefinedOffer, emptyVariables))
-			university->skills.push_back(skill.first);
-	}
-}
-
-std::string MarketInstanceConstructor::getSpeechTranslated() const
-{
-	assert(marketModes.count(EMarketMode::RESOURCE_SKILL));
-	return LIBRARY->generaltexth->translate(speechTextID);
-}
-
-int MarketInstanceConstructor::getMarketEfficiency() const
-{
-	return marketEfficiency;
-}
-
 VCMI_LIB_NAMESPACE_END
 VCMI_LIB_NAMESPACE_END

+ 0 - 23
lib/mapObjectConstructors/CommonConstructors.h

@@ -15,10 +15,8 @@
 #include "../mapObjects/MiscObjects.h"
 #include "../mapObjects/MiscObjects.h"
 #include "../mapObjects/CGCreature.h"
 #include "../mapObjects/CGCreature.h"
 #include "../mapObjects/CGHeroInstance.h"
 #include "../mapObjects/CGHeroInstance.h"
-#include "../mapObjects/CGMarket.h"
 #include "../mapObjects/CGResource.h"
 #include "../mapObjects/CGResource.h"
 #include "../mapObjects/CGTownInstance.h"
 #include "../mapObjects/CGTownInstance.h"
-#include "../mapObjects/ObstacleSetHandler.h"
 
 
 VCMI_LIB_NAMESPACE_BEGIN
 VCMI_LIB_NAMESPACE_BEGIN
 
 
@@ -126,25 +124,4 @@ public:
 	AnimationPath getBoatAnimationName() const;
 	AnimationPath getBoatAnimationName() const;
 };
 };
 
 
-class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
-{
-	std::string descriptionTextID;
-	std::string speechTextID;
-	
-	std::set<EMarketMode> marketModes;
-	JsonNode predefinedOffer;
-	int marketEfficiency;
-
-	void initTypeData(const JsonNode & config) override;
-public:
-	std::shared_ptr<CGMarket> createObject(IGameInfoCallback * cb) const override;
-	void randomizeObject(CGMarket * object, IGameRandomizer & gameRandomizer) const override;
-
-	const std::set<EMarketMode> & availableModes() const;
-	bool hasDescription() const;
-
-	std::string getSpeechTranslated() const;
-	int getMarketEfficiency() const;
-};
-
 VCMI_LIB_NAMESPACE_END
 VCMI_LIB_NAMESPACE_END

+ 121 - 0
lib/mapObjectConstructors/MarketInstanceConstructor.cpp

@@ -0,0 +1,121 @@
+/*
+* MarketInstanceConstructor.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 "MarketInstanceConstructor.h"
+
+#include "../CConfigHandler.h"
+#include "../GameLibrary.h"
+#include "../constants/StringConstants.h"
+#include "../json/JsonRandom.h"
+#include "../json/JsonUtils.h"
+#include "../texts/CGeneralTextHandler.h"
+#include "../texts/TextIdentifier.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+void MarketInstanceConstructor::initTypeData(const JsonNode & input)
+{
+	if (settings["mods"]["validation"].String() != "off")
+		JsonUtils::validate(input, "vcmi:market", getJsonKey());
+
+	if (!input["description"].isNull())
+	{
+		std::string description = input["description"].String();
+		if (!description.empty() && description.at(0) == '@')
+		{
+			descriptionTextID = description.substr(1);
+		}
+		else
+		{
+			descriptionTextID = TextIdentifier(getBaseTextID(), "description").get();
+			LIBRARY->generaltexth->registerString( input.getModScope(), descriptionTextID, input["description"]);
+		}
+	}
+
+	if (!input["speech"].isNull())
+	{
+		std::string speech = input["speech"].String();
+		if (!speech.empty() && speech.at(0) == '@')
+		{
+			speechTextID = speech.substr(1);
+		}
+		else
+		{
+			speechTextID = TextIdentifier(getBaseTextID(), "speech").get();
+			LIBRARY->generaltexth->registerString( input.getModScope(), speechTextID, input["speech"]);
+		}
+	}
+
+	for(auto & element : input["modes"].Vector())
+	{
+		if(MappedKeys::MARKET_NAMES_TO_TYPES.count(element.String()))
+			marketModes.insert(MappedKeys::MARKET_NAMES_TO_TYPES.at(element.String()));
+	}
+
+	marketEfficiency = input["efficiency"].isNull() ? 5 : input["efficiency"].Integer();
+	predefinedOffer = input["offer"];
+}
+
+bool MarketInstanceConstructor::hasDescription() const
+{
+	return !descriptionTextID.empty();
+}
+
+std::string MarketInstanceConstructor::getDescriptionTextID() const
+{
+	return descriptionTextID;
+}
+
+std::shared_ptr<CGMarket> MarketInstanceConstructor::createObject(IGameInfoCallback * cb) const
+{
+	if(marketModes.size() == 1)
+	{
+		switch(*marketModes.begin())
+		{
+			case EMarketMode::ARTIFACT_RESOURCE:
+			case EMarketMode::RESOURCE_ARTIFACT:
+				return std::make_shared<CGBlackMarket>(cb);
+
+			case EMarketMode::RESOURCE_SKILL:
+				return std::make_shared<CGUniversity>(cb);
+		}
+	}
+	return std::make_shared<CGMarket>(cb);
+}
+
+const std::set<EMarketMode> & MarketInstanceConstructor::availableModes() const
+{
+	return marketModes;
+}
+
+void MarketInstanceConstructor::randomizeObject(CGMarket * object, IGameRandomizer & gameRandomizer) const
+{
+	JsonRandom randomizer(object->cb, gameRandomizer);
+	JsonRandom::Variables emptyVariables;
+
+	if(auto * university = dynamic_cast<CGUniversity *>(object))
+	{
+		for(auto skill : randomizer.loadSecondaries(predefinedOffer, emptyVariables))
+			university->skills.push_back(skill.first);
+	}
+}
+
+std::string MarketInstanceConstructor::getSpeechTranslated() const
+{
+	assert(marketModes.count(EMarketMode::RESOURCE_SKILL));
+	return LIBRARY->generaltexth->translate(speechTextID);
+}
+
+int MarketInstanceConstructor::getMarketEfficiency() const
+{
+	return marketEfficiency;
+}
+
+VCMI_LIB_NAMESPACE_END

+ 40 - 0
lib/mapObjectConstructors/MarketInstanceConstructor.h

@@ -0,0 +1,40 @@
+/*
+* MarketInstanceConstructor.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 "CDefaultObjectTypeHandler.h"
+#include "../mapObjects/CGMarket.h"
+#include "../json/JsonNode.h"
+
+VCMI_LIB_NAMESPACE_BEGIN
+
+class MarketInstanceConstructor : public CDefaultObjectTypeHandler<CGMarket>
+{
+	std::string descriptionTextID;
+	std::string speechTextID;
+
+	std::set<EMarketMode> marketModes;
+	JsonNode predefinedOffer;
+	int marketEfficiency;
+
+	void initTypeData(const JsonNode & config) override;
+public:
+	std::shared_ptr<CGMarket> createObject(IGameInfoCallback * cb) const override;
+	void randomizeObject(CGMarket * object, IGameRandomizer & gameRandomizer) const override;
+
+	const std::set<EMarketMode> & availableModes() const;
+	bool hasDescription() const;
+	std::string getDescriptionTextID() const;
+
+	std::string getSpeechTranslated() const;
+	int getMarketEfficiency() const;
+};
+
+VCMI_LIB_NAMESPACE_END

+ 35 - 8
lib/mapObjects/CGMarket.cpp

@@ -11,18 +11,21 @@
 #include "StdInc.h"
 #include "StdInc.h"
 #include "CGMarket.h"
 #include "CGMarket.h"
 
 
-#include "../callback/IGameInfoCallback.h"
-#include "../callback/IGameEventCallback.h"
-#include "../callback/IGameRandomizer.h"
-#include "../texts/CGeneralTextHandler.h"
-#include "../CCreatureHandler.h"
+#include "CGHeroInstance.h"
 #include "CGTownInstance.h"
 #include "CGTownInstance.h"
+
+//#include "../CCreatureHandler.h"
+#include "../CPlayerState.h"
+//#include "../CSkillHandler.h"
 #include "../IGameSettings.h"
 #include "../IGameSettings.h"
-#include "../CSkillHandler.h"
+#include "../callback/IGameEventCallback.h"
+#include "../callback/IGameInfoCallback.h"
+#include "../callback/IGameRandomizer.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../mapObjectConstructors/AObjectTypeHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
 #include "../mapObjectConstructors/CObjectClassesHandler.h"
-#include "../mapObjectConstructors/CommonConstructors.h"
+#include "../mapObjectConstructors/MarketInstanceConstructor.h"
 #include "../networkPacks/PacksForClient.h"
 #include "../networkPacks/PacksForClient.h"
+#include "../texts/TextIdentifier.h"
 
 
 VCMI_LIB_NAMESPACE_BEGIN
 VCMI_LIB_NAMESPACE_BEGIN
 
 
@@ -48,7 +51,7 @@ std::string CGMarket::getPopupText(PlayerColor player) const
 
 
 	MetaString message = MetaString::createFromRawString("{%s}\r\n\r\n%s");
 	MetaString message = MetaString::createFromRawString("{%s}\r\n\r\n%s");
 	message.replaceName(ID, subID);
 	message.replaceName(ID, subID);
-	message.replaceTextID(TextIdentifier(getObjectHandler()->getBaseTextID(), "description").get());
+	message.replaceTextID(getMarketHandler()->getDescriptionTextID());
 	return message.toString();
 	return message.toString();
 }
 }
 
 
@@ -135,7 +138,31 @@ std::string CGUniversity::getSpeechTranslated() const
 
 
 void CGUniversity::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 void CGUniversity::onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const
 {
 {
+	ChangeObjectVisitors cow;
+	cow.object = id;
+	cow.mode = ChangeObjectVisitors::VISITOR_ADD_PLAYER;
+	cow.hero = h->id;
+	gameEvents.sendAndApply(cow);
+
 	gameEvents.showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true);
 	gameEvents.showObjectWindow(this, EOpenWindowMode::UNIVERSITY_WINDOW, h, true);
 }
 }
 
 
+bool CGUniversity::wasVisited (PlayerColor player) const
+{
+	return cb->getPlayerState(player)->visitedObjects.count(id) != 0;
+}
+
+std::vector<Component> CGUniversity::getPopupComponents(PlayerColor player) const
+{
+	std::vector<Component> result;
+
+	if (!wasVisited(player))
+		return result;
+
+	for (auto const & skill : skills)
+		result.emplace_back(ComponentType::SEC_SKILL, skill.as<SecondarySkill>());
+
+	return result;
+}
+
 VCMI_LIB_NAMESPACE_END
 VCMI_LIB_NAMESPACE_END

+ 2 - 0
lib/mapObjects/CGMarket.h

@@ -65,6 +65,8 @@ public:
 
 
 	std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
 	std::vector<TradeItemBuy> availableItemsIds(EMarketMode mode) const override;
 	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override; //open window
 	void onHeroVisit(IGameEventCallback & gameEvents, const CGHeroInstance * h) const override; //open window
+	std::vector<Component> getPopupComponents(PlayerColor player) const override;
+	bool wasVisited (PlayerColor player) const override;
 
 
 	template <typename Handler> void serialize(Handler &h)
 	template <typename Handler> void serialize(Handler &h)
 	{
 	{