浏览代码

Special buildings support : Patch 1

Dmitry Orlov 5 年之前
父节点
当前提交
934c4e511d

+ 26 - 17
client/windows/CCastleInterface.cpp

@@ -115,7 +115,7 @@ void CBuildingRect::clickLeft(tribool down, bool previousState)
 		if (!CSDL_Ext::isTransparent(area, GH.current->motion.x - pos.x, GH.current->motion.y - pos.y)) //inside building image
 		{
 			auto building = getBuilding();
-			parent->buildingClicked(building->bid, building->subId);
+			parent->buildingClicked(building->bid, building->subId, building->upgrade);
 		}
 }
 
@@ -653,7 +653,7 @@ const CGHeroInstance * CCastleBuildings::getHero()
 		return town->garrisonHero;
 }
 
-void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuildingSubID subID)
+void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuildingSubID subID, BuildingID::EBuildingID upgrades)
 {
 	logGlobal->trace("You've clicked on %d", (int)building.toEnum());
 	const CBuilding *b = town->town->buildings.find(building)->second;
@@ -719,7 +719,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
 						break;
 
 				case BuildingSubID::MYSTIC_POND:
-						enterFountain(building);
+						enterFountain(building, subID, upgrades);
 						break;
 
 				case BuildingSubID::ARTIFACT_MERCHANT:
@@ -730,7 +730,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
 						break;
 
 				case BuildingSubID::FOUNTAIN_OF_FORTUNE:
-						enterFountain(building);
+						enterFountain(building, subID, upgrades);
 						break;
 
 				case BuildingSubID::FREELANCERS_GUILD:
@@ -748,7 +748,10 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
 						break;
 
 				case BuildingSubID::BROTHERHOOD_OF_SWORD:
-						LOCPLINT->showTavernWindow(town);
+						if(upgrades == BuildingID::TAVERN)
+							LOCPLINT->showTavernWindow(town);
+						else
+							enterBuilding(building);
 						break;
 
 				case BuildingSubID::CASTLE_GATE:
@@ -839,22 +842,28 @@ void CCastleBuildings::enterToTheQuickRecruitmentWindow()
 	GH.pushIntT<QuickRecruitmentWindow>(town, pos);
 }
 
-void CCastleBuildings::enterFountain(BuildingID building)
+void CCastleBuildings::enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID::EBuildingID upgrades)
 {
-	std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(CComponent::building,town->subID,building));
-
+	std::vector<std::shared_ptr<CComponent>> comps(1, std::make_shared<CComponent>(CComponent::building,town->subID, building));
 	std::string descr = town->town->buildings.find(building)->second->Description();
 
-	if ( building == BuildingID::FOUNTAIN_OF_FORTUNE)
-		descr += "\n\n"+town->town->buildings.find(BuildingID::MYSTIC_POND)->second->Description();
+	bool isMysticPondOrItsUpgrade = subID == BuildingSubID::MYSTIC_POND 
+		|| (upgrades != BuildingID::NONE 
+			&& town->town->buildings.find(BuildingID(upgrades))->second->subId == BuildingSubID::MYSTIC_POND);
 
-	if (town->bonusValue.first == 0)//fountain was builded this week
-		descr += "\n\n"+ CGI->generaltexth->allTexts[677];
-	else//fountain produced something;
+	if(upgrades != BuildingID::NONE)
+		descr += "\n\n"+town->town->buildings.find(BuildingID(upgrades))->second->Description();
+
+	if(isMysticPondOrItsUpgrade) //for vanila Rampart like towns
 	{
-		descr+= "\n\n"+ CGI->generaltexth->allTexts[678];
-		boost::algorithm::replace_first(descr,"%s",CGI->generaltexth->restypes[town->bonusValue.first]);
-		boost::algorithm::replace_first(descr,"%d",boost::lexical_cast<std::string>(town->bonusValue.second));
+		if(town->bonusValue.first == 0) //Mystic Pond produced nothing;
+			descr += "\n\n" + CGI->generaltexth->allTexts[677];
+		else //Mystic Pond produced something;
+		{
+			descr += "\n\n" + CGI->generaltexth->allTexts[678];
+			boost::algorithm::replace_first(descr, "%s", CGI->generaltexth->restypes[town->bonusValue.first]);
+			boost::algorithm::replace_first(descr, "%d", boost::lexical_cast<std::string>(town->bonusValue.second));
+		}
 	}
 	LOCPLINT->showInfoDialog(descr, comps);
 }
@@ -1627,7 +1636,7 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding()
 	BuildingID myID = BuildingID(BuildingID::DWELL_FIRST).advance(level);
 
 	if (level == GameConstants::CREATURES_PER_TOWN)
-		return town->town->buildings.at(BuildingID::PORTAL_OF_SUMMON);
+		return town->town->getSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING);
 
 	if (!town->town->buildings.count(myID))
 		return nullptr;

+ 2 - 2
client/windows/CCastleInterface.h

@@ -136,7 +136,7 @@ class CCastleBuildings : public CIntObject
 	void enterBlacksmith(ArtifactID artifactID);//support for blacksmith + ballista yard
 	void enterBuilding(BuildingID building);//for buildings with simple description + pic left-click messages
 	void enterCastleGate();
-	void enterFountain(BuildingID building);//Rampart's fountains
+	void enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID::EBuildingID upgrades);//Rampart's fountains
 	void enterMagesGuild();
 	void enterTownHall();
 
@@ -153,7 +153,7 @@ public:
 	void enterDwelling(int level);
 	void enterToTheQuickRecruitmentWindow();
 
-	void buildingClicked(BuildingID building, BuildingSubID::EBuildingSubID subID = BuildingSubID::NONE);
+	void buildingClicked(BuildingID building, BuildingSubID::EBuildingSubID subID = BuildingSubID::NONE, BuildingID::EBuildingID upgrades = BuildingID::NONE);
 	void addBuilding(BuildingID building);
 	void removeBuilding(BuildingID building);//FIXME: not tested!!!
 };

+ 1 - 1
config/factions/rampart.json

@@ -177,7 +177,7 @@
 				"special1":       { "type" : "mysticPond" },
 				"horde1":         { "id" : 18, "upgrades" : "dwellingLvl2" },
 				"horde1Upgr":     { "id" : 19, "upgrades" : "dwellingUpLvl2", "requires" : [ "horde1" ], "mode" : "auto" },
-				"special2":       { "type" : "fountainOfFortune", "requires" : [ "special1" ] },
+				"special2":       { "type" : "fountainOfFortune", "upgrades" : "special1" },
 				"special3":       { "requires" : [ "horde1" ] },
 				"horde2":         { "id" : 24, "upgrades" : "dwellingLvl5" },
 				"horde2Upgr":     { "id" : 25, "upgrades" : "dwellingUpLvl5", "requires" : [ "horde2" ], "mode" : "auto" },

+ 15 - 0
lib/CTownHandler.cpp

@@ -201,6 +201,21 @@ std::set<si32> CTown::getAllBuildings() const
 	return res;
 }
 
+const CBuilding * CTown::getSpecialBuilding(BuildingSubID::EBuildingSubID subID) const
+{
+	for(const auto & kvp : buildings)
+	{
+		if(kvp.second->subId == subID)
+			return buildings.at(kvp.first);
+	}
+	return nullptr;
+}
+
+BuildingID::EBuildingID CTown::getBuildingType(BuildingSubID::EBuildingSubID subID) const
+{
+	auto building = getSpecialBuilding(subID);
+	return building == nullptr ? BuildingID::NONE : building->bid.num;
+}
 
 CTownHandler::CTownHandler()
 {

+ 9 - 0
lib/CTownHandler.h

@@ -78,6 +78,13 @@ public:
 
 	// returns how many times build has to be upgraded to become build
 	si32 getDistance(BuildingID build) const;
+
+	STRONG_INLINE
+	bool IsTradeBuilding() const
+	{
+		return bid == BuildingID::MARKETPLACE || subId == BuildingSubID::ARTIFACT_MERCHANT || subId == BuildingSubID::FREELANCERS_GUILD;
+	}
+
 	/// input: faction, bid; output: subId, height;
 	void update792(const BuildingID & bid, BuildingSubID::EBuildingSubID & subId, ETowerHeight & height);
 
@@ -204,6 +211,8 @@ public:
 	std::string getFactionName() const;
 	std::string getBuildingScope() const;
 	std::set<si32> getAllBuildings() const;
+	const CBuilding * getSpecialBuilding(BuildingSubID::EBuildingSubID subID) const;
+	BuildingID::EBuildingID getBuildingType(BuildingSubID::EBuildingSubID subID) const;
 
 	CFaction * faction;
 

+ 52 - 64
lib/mapObjects/CGTownInstance.cpp

@@ -739,23 +739,29 @@ std::string CGTownInstance::getObjectName() const
 	return name + ", " + town->faction->name;
 }
 
-bool CGTownInstance::townEnvisagesSpecialBuilding(BuildingSubID::EBuildingSubID bid) const
+bool CGTownInstance::townEnvisagesBuilding(BuildingSubID::EBuildingSubID subId) const
 {
-	for(const auto & it : town->buildings)
-	{
-		if(it.second->subId == bid)
-			return true;
-	}
-	return false;
+	return town->getBuildingType(subId) != BuildingID::NONE;
+}
+
+//it does not check hasBuilt(...) because this check is in the OnHeroVisit handler
+bool CGTownInstance::tryAddOnePerWeekBonus(BuildingSubID::EBuildingSubID subID)
+{
+	auto bid = town->getBuildingType(subID);
+
+	if(bid == BuildingID::NONE)
+		return false;
+
+	bonusingBuildings.push_back(new COPWBonus(bid, subID, this));
+	return true;
 }
 
-void CGTownInstance::initObj(CRandomGenerator & rand)
-///initialize town structures
+void CGTownInstance::initObj(CRandomGenerator & rand) ///initialize town structures
 {
 	blockVisit = true;
 
-	if(townEnvisagesSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING)) //Dungeon for example
-		creatures.resize(GameConstants::CREATURES_PER_TOWN+1);
+	if(townEnvisagesBuilding(BuildingSubID::PORTAL_OF_SUMMONING)) //Dungeon for example
+		creatures.resize(GameConstants::CREATURES_PER_TOWN + 1);
 	else
 		creatures.resize(GameConstants::CREATURES_PER_TOWN);
 
@@ -770,11 +776,8 @@ void CGTownInstance::initObj(CRandomGenerator & rand)
 				creatures[level].second.push_back(town->creatures[level][upgradeNum]);
 		}
 	}
-	if(townEnvisagesSpecialBuilding(BuildingSubID::STABLES))
-		bonusingBuildings.push_back(new COPWBonus(BuildingID::STABLES, BuildingSubID::STABLES, this));
-
-	if(townEnvisagesSpecialBuilding(BuildingSubID::MANA_VORTEX))
-		bonusingBuildings.push_back(new COPWBonus(BuildingID::MANA_VORTEX, BuildingSubID::MANA_VORTEX, this));
+	tryAddOnePerWeekBonus(BuildingSubID::STABLES);
+	tryAddOnePerWeekBonus(BuildingSubID::MANA_VORTEX);
 
 	switch (subID)
 	{
@@ -824,45 +827,22 @@ void CGTownInstance::updateBonusingBuildings()
 		switch (building->subId)
 		{
 		case BuildingSubID::PORTAL_OF_SUMMONING:
-			creatures.resize(GameConstants::CREATURES_PER_TOWN + 1);
+			if(!hasBuiltInOldWay(ETownType::DUNGEON, BuildingID::PORTAL_OF_SUMMON))
+				creatures.resize(GameConstants::CREATURES_PER_TOWN + 1);
 			break;
 		///'hasBuilt' checking for COPW bonuses is in the COPWBonus::onHeroVisit
 		case BuildingSubID::STABLES:
 			if(getBonusingBuilding(building->subId) == nullptr)
-				bonusingBuildings.push_back(new COPWBonus(BuildingID::STABLES, BuildingSubID::STABLES, this));
+				tryAddOnePerWeekBonus(BuildingSubID::STABLES);
 			break;
 
 		case BuildingSubID::MANA_VORTEX:
 			if(getBonusingBuilding(building->subId) == nullptr)
-				bonusingBuildings.push_back(new COPWBonus(BuildingID::MANA_VORTEX, BuildingSubID::MANA_VORTEX, this));
-			break;
-		///add new bonus if bonusing building was built in the user added towns:
-		case BuildingSubID::BROTHERHOOD_OF_SWORD:
-			if(!hasBuiltInOldWay(ETownType::CASTLE, BuildingID::BROTHERHOOD))
-				addBonusIfBuilt(BuildingID::BROTHERHOOD, BuildingSubID::BROTHERHOOD_OF_SWORD, Bonus::MORALE, +2);
-			break;
-
-		case BuildingSubID::FOUNTAIN_OF_FORTUNE:
-			if(!hasBuiltInOldWay(ETownType::RAMPART, BuildingID::FOUNTAIN_OF_FORTUNE))
-				addBonusIfBuilt(BuildingID::FOUNTAIN_OF_FORTUNE, BuildingSubID::FOUNTAIN_OF_FORTUNE, Bonus::LUCK, +2);
-			break;
-
-		case BuildingSubID::SPELL_POWER_GARRISON_BONUS:
-			if(!hasBuiltInOldWay(ETownType::INFERNO, BuildingID::STORMCLOUDS))
-				addBonusIfBuilt(BuildingID::STORMCLOUDS, BuildingSubID::SPELL_POWER_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::SPELL_POWER);
-			break;
-
-		case BuildingSubID::ATTACK_GARRISON_BONUS:
-			if(!hasBuiltInOldWay(ETownType::FORTRESS, BuildingID::BLOOD_OBELISK))
-				addBonusIfBuilt(BuildingID::BLOOD_OBELISK, BuildingSubID::ATTACK_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::ATTACK);
-			break;
-
-		case BuildingSubID::DEFENSE_GARRISON_BONUS:
-			if(!hasBuiltInOldWay(ETownType::FORTRESS, BuildingID::GLYPHS_OF_FEAR))
-				addBonusIfBuilt(BuildingID::GLYPHS_OF_FEAR, BuildingSubID::DEFENSE_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::DEFENSE);
+				tryAddOnePerWeekBonus(BuildingSubID::MANA_VORTEX);
 			break;
 		}
 	}
+	recreateBuildingsBonuses(); ///Clear all bonuses and recreate
 }
 
 bool CGTownInstance::hasBuiltInOldWay(ETownType::ETownType type, BuildingID bid) const
@@ -1071,7 +1051,7 @@ int CGTownInstance::getBoatType() const
 
 int CGTownInstance::getMarketEfficiency() const
 {
-	if (!hasBuilt(BuildingID::MARKETPLACE))
+	if(!hasBuiltSomeTradeBuilding())
 		return 0;
 
 	const PlayerState *p = cb->getPlayer(tempOwner);
@@ -1079,7 +1059,7 @@ int CGTownInstance::getMarketEfficiency() const
 
 	int marketCount = 0;
 	for(const CGTownInstance *t : p->towns)
-		if(t->hasBuilt(BuildingID::MARKETPLACE))
+		if(t->hasBuiltSomeTradeBuilding())
 			marketCount++;
 
 	return marketCount;
@@ -1095,18 +1075,16 @@ bool CGTownInstance::allowsTrade(EMarketMode::EMarketMode mode) const
 
 	case EMarketMode::ARTIFACT_RESOURCE:
 	case EMarketMode::RESOURCE_ARTIFACT:
-		return hasBuilt(BuildingID::ARTIFACT_MERCHANT, ETownType::TOWER)
-		    || hasBuilt(BuildingID::ARTIFACT_MERCHANT, ETownType::DUNGEON)
-		    || hasBuilt(BuildingID::ARTIFACT_MERCHANT, ETownType::CONFLUX);
+		return hasBuilt(BuildingSubID::ARTIFACT_MERCHANT);
 
 	case EMarketMode::CREATURE_RESOURCE:
-		return hasBuilt(BuildingID::FREELANCERS_GUILD, ETownType::STRONGHOLD);
+		return hasBuilt(BuildingSubID::FREELANCERS_GUILD);
 
 	case EMarketMode::CREATURE_UNDEAD:
-		return hasBuilt(BuildingID::SKELETON_TRANSFORMER, ETownType::NECROPOLIS);
+		return hasBuilt(BuildingSubID::CREATURE_TRANSFORMER);
 
 	case EMarketMode::RESOURCE_SKILL:
-		return hasBuilt(BuildingID::MAGIC_UNIVERSITY, ETownType::CONFLUX);
+		return hasBuilt(BuildingSubID::MAGIC_UNIVERSITY);
 	default:
 		assert(0);
 		return false;
@@ -1195,13 +1173,13 @@ void CGTownInstance::recreateBuildingsBonuses()
 		removeBonus(b);
 
 	//tricky! -> checks tavern only if no bratherhood of sword or not a castle
-	if(!addBonusIfBuilt(BuildingID::BROTHERHOOD, BuildingSubID::BROTHERHOOD_OF_SWORD, Bonus::MORALE, +2))
+	if(!addBonusIfBuilt(BuildingSubID::BROTHERHOOD_OF_SWORD, Bonus::MORALE, +2))
 		addBonusIfBuilt(BuildingID::TAVERN, Bonus::MORALE, +1);
 
-	addBonusIfBuilt(BuildingID::FOUNTAIN_OF_FORTUNE, BuildingSubID::FOUNTAIN_OF_FORTUNE, Bonus::LUCK, +2); //fountain of fortune
-	addBonusIfBuilt(BuildingID::STORMCLOUDS, BuildingSubID::SPELL_POWER_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::SPELL_POWER);//works as Brimstone Clouds
-	addBonusIfBuilt(BuildingID::BLOOD_OBELISK, BuildingSubID::ATTACK_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::ATTACK);//works as Blood Obelisk
-	addBonusIfBuilt(BuildingID::GLYPHS_OF_FEAR, BuildingSubID::DEFENSE_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::DEFENSE);//works as Glyphs of Fear
+	addBonusIfBuilt(BuildingSubID::FOUNTAIN_OF_FORTUNE, Bonus::LUCK, +2); //fountain of fortune
+	addBonusIfBuilt(BuildingSubID::SPELL_POWER_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::SPELL_POWER);//works as Brimstone Clouds
+	addBonusIfBuilt(BuildingSubID::ATTACK_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::ATTACK);//works as Blood Obelisk
+	addBonusIfBuilt(BuildingSubID::DEFENSE_GARRISON_BONUS, Bonus::PRIMARY_SKILL, +2, PrimarySkill::DEFENSE);//works as Glyphs of Fear
 
 	if(subID == ETownType::CASTLE) //castle
 	{
@@ -1237,23 +1215,22 @@ void CGTownInstance::recreateBuildingsBonuses()
 	}
 }
 
-bool CGTownInstance::addBonusIfBuilt(BuildingID bid, BuildingSubID::EBuildingSubID subId, Bonus::BonusType type, int val, int subtype)
+bool CGTownInstance::addBonusIfBuilt(BuildingSubID::EBuildingSubID subId, Bonus::BonusType type, int val, int subtype)
 {
-	bool hasBuilt = false;
+	BuildingID currentBid = BuildingID::NONE;
 	std::ostringstream descr;
 
-	for (const auto & bid : builtBuildings)
+	for(const auto & bid : builtBuildings)
 	{
 		if (town->buildings.at(bid)->subId == subId)
 		{
 			descr << town->buildings.at(bid)->Name();
-			hasBuilt = true;
+			currentBid = bid;
 			break;
 		}
 	}
-	if(hasBuilt)
-		hasBuilt = addBonusImpl(bid, type, val, emptyPropagator, descr.str(), subtype);
-	return hasBuilt;
+	return currentBid == BuildingID::NONE ? false
+		: addBonusImpl(currentBid, type, val, emptyPropagator, descr.str(), subtype);
 }
 
 bool CGTownInstance::addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, int subtype)
@@ -1390,6 +1367,17 @@ const CGTownBuilding * CGTownInstance::getBonusingBuilding(BuildingSubID::EBuild
 	return nullptr;
 }
 
+
+bool CGTownInstance::hasBuiltSomeTradeBuilding() const
+{
+	for (const auto & bid : builtBuildings)
+	{
+		if(town->buildings.at(bid)->IsTradeBuilding())
+			return true;
+	}
+	return false;
+}
+
 bool CGTownInstance::hasBuilt(BuildingSubID::EBuildingSubID buildingID) const
 {
 	for(const auto & bid : builtBuildings)

+ 6 - 2
lib/mapObjects/CGTownInstance.h

@@ -262,7 +262,7 @@ public:
 	void deserializationFix();
 	void recreateBuildingsBonuses();
 	///bid: param to bind a building with a bonus, subId: param to check if already built
-	bool addBonusIfBuilt(BuildingID bid, BuildingSubID::EBuildingSubID subId, Bonus::BonusType type, int val, int subtype = -1);
+	bool addBonusIfBuilt(BuildingSubID::EBuildingSubID subId, Bonus::BonusType type, int val, int subtype = -1);
 	bool addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr &prop, int subtype = -1); //returns true if building is built and bonus has been added
 	bool addBonusIfBuilt(BuildingID building, Bonus::BonusType type, int val, int subtype = -1); //convienence version of above
 	void setVisitingHero(CGHeroInstance *h);
@@ -295,6 +295,7 @@ public:
 	bool hasFort() const;
 	bool hasCapitol() const;
 	const CGTownBuilding * getBonusingBuilding(BuildingSubID::EBuildingSubID subId) const;
+	bool hasBuiltSomeTradeBuilding() const;
 	//checks if special building with type buildingID is constructed
 	bool hasBuilt(BuildingSubID::EBuildingSubID buildingID) const;
 	//checks if building is constructed and town has same subID
@@ -313,7 +314,6 @@ public:
 	void removeCapitols (PlayerColor owner) const;
 	void clearArmy() const;
 	void addHeroToStructureVisitors(const CGHeroInstance *h, si64 structureInstanceID) const; //hero must be visiting or garrisoned in town
-	bool townEnvisagesSpecialBuilding(BuildingSubID::EBuildingSubID bid) const;
 
 	const CTown * getTown() const ;
 
@@ -330,13 +330,17 @@ public:
 
 	void afterAddToMap(CMap * map) override;
 	static void reset();
+
 protected:
 	static TPropagatorPtr emptyPropagator;
 	void setPropertyDer(ui8 what, ui32 val) override;
 	void serializeJsonOptions(JsonSerializeFormat & handler) override;
+
 private:
 	int getDwellingBonus(const std::vector<CreatureID>& creatureIds, const std::vector<ConstTransitivePtr<CGDwelling> >& dwellings) const;
 	void updateBonusingBuildings();
 	bool hasBuiltInOldWay(ETownType::ETownType type, BuildingID bid) const;
 	bool addBonusImpl(BuildingID building, Bonus::BonusType type, int val, TPropagatorPtr & prop, const std::string & description, int subtype = -1);
+	bool townEnvisagesBuilding(BuildingSubID::EBuildingSubID bid) const;
+	bool tryAddOnePerWeekBonus(BuildingSubID::EBuildingSubID subID);
 };

+ 5 - 5
server/CGameHandler.cpp

@@ -1808,7 +1808,7 @@ void CGameHandler::newTurn()
 		handleTownEvents(t, n);
 		if (newWeek) //first day of week
 		{
-			if (t->hasBuilt(BuildingID::PORTAL_OF_SUMMON, ETownType::DUNGEON))
+			if (t->hasBuilt(BuildingSubID::PORTAL_OF_SUMMONING))
 				setPortalDwelling(t, true, (n.specialWeek == NewTurn::PLAGUE ? true : false)); //set creatures for Portal of Summoning
 
 			if (!firstTurn)
@@ -2391,7 +2391,7 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, PlayerColor owner)
 	{
 		if (owner < PlayerColor::PLAYER_LIMIT) //new owner is real player
 		{
-			if (town->hasBuilt(BuildingID::PORTAL_OF_SUMMON, ETownType::DUNGEON))
+			if (town->hasBuilt(BuildingSubID::PORTAL_OF_SUMMONING))
 				setPortalDwelling(town, true, false);
 		}
 
@@ -2414,7 +2414,7 @@ void CGameHandler::setOwner(const CGObjectInstance * obj, PlayerColor owner)
 	{
 		for (const CGTownInstance * t : getPlayer(owner)->towns)
 		{
-			if (t->hasBuilt(BuildingID::PORTAL_OF_SUMMON, ETownType::DUNGEON))
+			if (t->hasBuilt(BuildingSubID::PORTAL_OF_SUMMONING))
 				setPortalDwelling(t);//set initial creatures for all portals of summoning
 		}
 	}
@@ -3076,7 +3076,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
 			ssi.creatures[level].second.push_back(crea->idNumber);
 			sendAndApply(&ssi);
 		}
-		if (t->subID == ETownType::DUNGEON && buildingID == BuildingID::PORTAL_OF_SUMMON)
+		if (t->town->buildings.at(buildingID)->subId == BuildingSubID::PORTAL_OF_SUMMONING)
 		{
 			setPortalDwelling(t);
 		}
@@ -3541,7 +3541,7 @@ bool CGameHandler::buyArtifact(ObjectInstanceID hid, ArtifactID aid)
 		COMPLAIN_RET_FALSE_IF(getPlayer(hero->getOwner())->resources.at(Res::GOLD) < price, "Not enough gold!");
 
 		if  ((town->hasBuilt(BuildingID::BLACKSMITH) && town->town->warMachine == aid)
-		 || ((town->hasBuilt(BuildingID::BALLISTA_YARD, ETownType::STRONGHOLD)) && aid == ArtifactID::BALLISTA))
+		 || (town->hasBuilt(BuildingSubID::BALLISTA_YARD) && aid == ArtifactID::BALLISTA))
 		{
 			giveResource(hero->getOwner(),Res::GOLD,-price);
 			return giveHeroNewArtifact(hero, art);