瀏覽代碼

Merge pull request #4348 from MichalZr6/hill_fort_changes

Hill Fort unavailable upgrade and status bar new messages
Ivan Savenko 11 月之前
父節點
當前提交
f8b1f40abb

+ 3 - 1
Mods/vcmi/config/vcmi/english.json

@@ -552,7 +552,9 @@
 	"core.seerhut.quest.reachDate.visit.3" : "Closed till %s.",
 	"core.seerhut.quest.reachDate.visit.4" : "Closed till %s.",
 	"core.seerhut.quest.reachDate.visit.5" : "Closed till %s.",
-
+	
+	"mapObject.core.hillFort.object.description" : "Upgrades creatures. Levels 1 - 4 are less expensive than in associated town.",
+	
 	"core.bonus.ADDITIONAL_ATTACK.name": "Double Strike",
 	"core.bonus.ADDITIONAL_ATTACK.description": "Attacks twice",
 	"core.bonus.ADDITIONAL_RETALIATION.name": "Additional retaliations",

+ 3 - 1
Mods/vcmi/config/vcmi/polish.json

@@ -532,7 +532,9 @@
 	"core.seerhut.quest.reachDate.visit.3" : "Zamknięte do %s.",
 	"core.seerhut.quest.reachDate.visit.4" : "Zamknięte do %s.",
 	"core.seerhut.quest.reachDate.visit.5" : "Zamknięte do %s.",
-
+	
+	"mapObject.core.hillFort.object.description" : "Ulepsza jednostki. Koszt ulepszenia dla poziomów 1 - 4 jest bardziej korzystny niż w mieście.",
+	
 	"core.bonus.ADDITIONAL_ATTACK.name": "Podwójne Uderzenie",
 	"core.bonus.ADDITIONAL_ATTACK.description": "Atakuje dwa razy",
 	"core.bonus.ADDITIONAL_RETALIATION.name": "Dodatkowy odwet",

+ 58 - 29
client/windows/GUIClasses.cpp

@@ -1113,6 +1113,9 @@ CHillFortWindow::CHillFortWindow(const CGHeroInstance * visitor, const CGObjectI
 	statusbar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
 
 	garr = std::make_shared<CGarrisonInt>(Point(108, 60), 18, Point(), hero, nullptr);
+
+	statusbar->write(VLC->generaltexth->translate(dynamic_cast<const HillFort *>(fort)->getDescriptionToolTip()));
+
 	updateGarrisons();
 }
 
@@ -1130,45 +1133,59 @@ void CHillFortWindow::updateGarrisons()
 
 	TResources totalSum; // totalSum[resource ID] = value
 
+	auto getImgIdx = [](CHillFortWindow::State st) -> std::size_t
+	{
+		switch (st)
+		{
+		case State::EMPTY:
+			return 0;
+		case State::UNAVAILABLE:
+		case State::ALREADY_UPGRADED:
+			return 1;
+		default:
+			return static_cast<std::size_t>(st);
+		}
+	};
+
 	for(int i=0; i<slotsCount; i++)
 	{
 		std::fill(costs[i].begin(), costs[i].end(), 0);
-		int newState = getState(SlotID(i));
-		if(newState != -1)
+		State newState = getState(SlotID(i));
+		if(newState != State::EMPTY)
 		{
 			UpgradeInfo info;
 			LOCPLINT->cb->fillUpgradeInfo(hero, SlotID(i), info);
 			if(info.newID.size())//we have upgrades here - update costs
 			{
-				costs[i] = info.cost[0] * hero->getStackCount(SlotID(i));
+				costs[i] = info.cost.back() * hero->getStackCount(SlotID(i));
 				totalSum += costs[i];
 			}
 		}
 
 		currState[i] = newState;
-		upgrade[i]->setImage(AnimationPath::builtin(currState[i] == -1 ? slotImages[0] : slotImages[currState[i]]));
-		upgrade[i]->block(currState[i] == -1);
+		upgrade[i]->setImage(AnimationPath::builtin(slotImages[getImgIdx(currState[i])]));
+		upgrade[i]->block(currState[i] == State::EMPTY);
 		upgrade[i]->addHoverText(EButtonState::NORMAL, getTextForSlot(SlotID(i)));
 	}
 
 	//"Upgrade all" slot
-	int newState = 2;
+	State newState = State::MAKE_UPGRADE;
 	{
 		TResources myRes = LOCPLINT->cb->getResourceAmount();
 
 		bool allUpgraded = true;//All creatures are upgraded?
 		for(int i=0; i<slotsCount; i++)
-			allUpgraded &= currState[i] == 1 || currState[i] == -1;
+			allUpgraded &= currState[i] == State::ALREADY_UPGRADED || currState[i] == State::EMPTY || currState[i] == State::UNAVAILABLE;
 
-		if(allUpgraded)
-			newState = 1;
+		if (allUpgraded)
+			newState = State::ALREADY_UPGRADED;
 
 		if(!totalSum.canBeAfforded(myRes))
-			newState = 0;
+			newState = State::UNAFFORDABLE;
 	}
 
 	currState[slotsCount] = newState;
-	upgradeAll->setImage(AnimationPath::builtin(allImages[newState]));
+	upgradeAll->setImage(AnimationPath::builtin(allImages[static_cast<std::size_t>(newState)]));
 
 	garr->recreateSlots();
 
@@ -1181,7 +1198,7 @@ void CHillFortWindow::updateGarrisons()
 			slotLabels[i][j]->setText("");
 		}
 		//if can upgrade or can not afford, draw cost
-		if(currState[i] == 0 || currState[i] == 2)
+		if(currState[i] == State::UNAFFORDABLE || currState[i] == State::MAKE_UPGRADE)
 		{
 			if(costs[i].nonZero())
 			{
@@ -1226,24 +1243,30 @@ void CHillFortWindow::updateGarrisons()
 
 void CHillFortWindow::makeDeal(SlotID slot)
 {
-	assert(slot.getNum()>=0);
-	int offset = (slot.getNum() == slotsCount)?2:0;
+	assert(slot.getNum() >= 0);
+	int offset = (slot.getNum() == slotsCount) ? 2 : 0;
 	switch(currState[slot.getNum()])
 	{
-		case 0:
+		case State::ALREADY_UPGRADED:
+			LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[313 + offset], std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
+			break;
+		case State::UNAFFORDABLE:
 			LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[314 + offset], std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
 			break;
-		case 1:
-			LOCPLINT->showInfoDialog(CGI->generaltexth->allTexts[313 + offset], std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
+		case State::UNAVAILABLE:
+		{
+			std::string message = VLC->generaltexth->translate(dynamic_cast<const HillFort *>(fort)->getUnavailableUpgradeMessage());
+			LOCPLINT->showInfoDialog(message, std::vector<std::shared_ptr<CComponent>>(), soundBase::sound_todo);
 			break;
-		case 2:
-			for(int i=0; i<slotsCount; i++)
+		}
+		case State::MAKE_UPGRADE:
+			for(int i = 0; i < slotsCount; i++)
 			{
-				if(slot.getNum() ==i || ( slot.getNum() == slotsCount && currState[i] == 2 ))//this is activated slot or "upgrade all"
+				if(slot.getNum() == i || ( slot.getNum() == slotsCount && currState[i] == State::MAKE_UPGRADE ))//this is activated slot or "upgrade all"
 				{
 					UpgradeInfo info;
 					LOCPLINT->cb->fillUpgradeInfo(hero, SlotID(i), info);
-					LOCPLINT->cb->upgradeCreature(hero, SlotID(i), info.newID[0]);
+					LOCPLINT->cb->upgradeCreature(hero, SlotID(i), info.newID.back());
 				}
 			}
 			break;
@@ -1265,22 +1288,28 @@ std::string CHillFortWindow::getTextForSlot(SlotID slot)
 	return str;
 }
 
-int CHillFortWindow::getState(SlotID slot)
+CHillFortWindow::State CHillFortWindow::getState(SlotID slot)
 {
 	TResources myRes = LOCPLINT->cb->getResourceAmount();
 
-	if(hero->slotEmpty(slot))//no creature here
-		return -1;
+	if(hero->slotEmpty(slot))
+		return State::EMPTY;
 
 	UpgradeInfo info;
 	LOCPLINT->cb->fillUpgradeInfo(hero, slot, info);
-	if(!info.newID.size())//already upgraded
-		return 1;
+	if (info.newID.empty())
+	{
+		// Hill Fort may limit level of upgradeable creatures, e.g. mini Hill Fort from HOTA
+		if (hero->getCreature(slot)->hasUpgrades())
+			return State::UNAVAILABLE;
+
+		return State::ALREADY_UPGRADED;
+	}
 
-	if(!(info.cost[0] * hero->getStackCount(slot)).canBeAfforded(myRes))
-		return 0;
+	if(!(info.cost.back() * hero->getStackCount(slot)).canBeAfforded(myRes))
+		return State::UNAFFORDABLE;
 
-	return 2;//can upgrade
+	return State::MAKE_UPGRADE;
 }
 
 CThievesGuildWindow::CThievesGuildWindow(const CGObjectInstance * _owner):

+ 6 - 4
client/windows/GUIClasses.h

@@ -449,9 +449,11 @@ public:
 class CHillFortWindow : public CStatusbarWindow, public IGarrisonHolder
 {
 private:
-	static const int slotsCount = 7;
+
+	enum class State { UNAFFORDABLE, ALREADY_UPGRADED, MAKE_UPGRADE, EMPTY, UNAVAILABLE };
+	static constexpr std::size_t slotsCount = 7;
 	//todo: mithril support
-	static const int resCount = 7;
+	static constexpr std::size_t resCount = 7;
 
 	const CGObjectInstance * fort;
 	const CGHeroInstance * hero;
@@ -463,7 +465,7 @@ private:
 	std::array<std::shared_ptr<CLabel>, resCount> totalLabels;
 
 	std::array<std::shared_ptr<CButton>, slotsCount> upgrade;//upgrade single creature
-	std::array<int, slotsCount + 1> currState;//current state of slot - to avoid calls to getState or updating buttons
+	std::array<State, slotsCount + 1> currState;//current state of slot - to avoid calls to getState or updating buttons
 
 	//there is a place for only 2 resources per slot
 	std::array< std::array<std::shared_ptr<CAnimImage>, 2>, slotsCount> slotIcons;
@@ -478,7 +480,7 @@ private:
 	std::string getTextForSlot(SlotID slot);
 
 	void makeDeal(SlotID slot);//-1 for upgrading all creatures
-	int getState(SlotID slot); //-1 = no creature 0=can't upgrade, 1=upgraded, 2=can upgrade
+	State getState(SlotID slot);
 public:
 	CHillFortWindow(const CGHeroInstance * visitor, const CGObjectInstance * object);
 	void updateGarrisons() override;//update buttons after garrison changes

+ 1 - 0
config/objects/generic.json

@@ -666,6 +666,7 @@
 			"object" : {
 				"index" : 0,
 				"aiValue" : 7000,
+				"description" : "",
 				"rmg" : {
 					"zoneLimit"	: 1,
 					"value"		: 7000,

+ 3 - 0
lib/mapObjectConstructors/HillFortInstanceConstructor.cpp

@@ -11,12 +11,15 @@
 #include "HillFortInstanceConstructor.h"
 
 #include "../mapObjects/MiscObjects.h"
+#include "../texts/CGeneralTextHandler.h"
 
 VCMI_LIB_NAMESPACE_BEGIN
 
 void HillFortInstanceConstructor::initTypeData(const JsonNode & config)
 {
 	parameters = config;
+	VLC->generaltexth->registerString(parameters.getModScope(), TextIdentifier(getBaseTextID(), "unavailableUpgradeMessage"), parameters["unavailableUpgradeMessage"].String());
+	VLC->generaltexth->registerString(parameters.getModScope(), TextIdentifier(getBaseTextID(), "description"), parameters["description"].String());
 }
 
 void HillFortInstanceConstructor::initializeObject(HillFort * fort) const

+ 10 - 0
lib/mapObjects/MiscObjects.cpp

@@ -1333,4 +1333,14 @@ void HillFort::fillUpgradeInfo(UpgradeInfo & info, const CStackInstance &stack)
 	}
 }
 
+std::string HillFort::getDescriptionToolTip() const
+{
+	return TextIdentifier(getObjectHandler()->getBaseTextID(), "description").get();
+}
+
+std::string HillFort::getUnavailableUpgradeMessage() const
+{
+	return TextIdentifier(getObjectHandler()->getBaseTextID(), "unavailableUpgradeMessage").get();
+}
+
 VCMI_LIB_NAMESPACE_END

+ 3 - 0
lib/mapObjects/MiscObjects.h

@@ -437,6 +437,9 @@ protected:
 public:
 	using CGObjectInstance::CGObjectInstance;
 
+	std::string getDescriptionToolTip() const;
+	std::string getUnavailableUpgradeMessage() const;
+
 	template <typename Handler> void serialize(Handler &h)
 	{
 		h & static_cast<CGObjectInstance&>(*this);