2
0
mateuszb 12 жил өмнө
parent
commit
8a8eecd063

+ 30 - 28
AI/VCAI/VCAI.cpp

@@ -844,7 +844,7 @@ void VCAI::objectPropertyChanged(const SetObjectProperty * sop)
 	}
 }
 
-void VCAI::buildChanged(const CGTownInstance *town, int buildingID, int what)
+void VCAI::buildChanged(const CGTownInstance *town, BuildingID buildingID, int what)
 {
 	NET_EVENT_HANDLER;
 	LOG_ENTRY;
@@ -1256,7 +1256,7 @@ void VCAI::recruitCreatures(const CGDwelling * d)
 	}
 }
 
-bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned int maxDays)
+bool VCAI::tryBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays)
 {
 	if (!vstd::contains(t->town->buildings, building))
 		return false; // no such building in town
@@ -1264,7 +1264,7 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
 	if (t->hasBuilt(building)) //Already built? Shouldn't happen in general
 		return true;
 
-	std::set<int> toBuild = cb->getBuildingRequiments(t, building);
+	std::set<BuildingID> toBuild = cb->getBuildingRequiments(t, building);
 
 	//erase all already built buildings
 	for (auto buildIter = toBuild.begin(); buildIter != toBuild.end();)
@@ -1277,7 +1277,7 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
 
 	toBuild.insert(building);
 
-	BOOST_FOREACH(int buildID, toBuild)
+	BOOST_FOREACH(BuildingID buildID, toBuild)
 	{
 		EBuildingState::EBuildingState canBuild = cb->canBuildStructure(t, buildID);
 		if (canBuild == EBuildingState::HAVE_CAPITAL
@@ -1293,7 +1293,7 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
 	TResources income = estimateIncome();
 	//TODO: calculate if we have enough resources to build it in maxDays
 
-	BOOST_FOREACH(int buildID, toBuild)
+	BOOST_FOREACH(const auto & buildID, toBuild)
 	{
 		const CBuilding *b = t->town->buildings[buildID];
 
@@ -1323,9 +1323,9 @@ bool VCAI::tryBuildStructure(const CGTownInstance * t, int building, unsigned in
 	return false;
 }
 
-bool VCAI::tryBuildAnyStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays)
+bool VCAI::tryBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays)
 {
-	BOOST_FOREACH(int building, buildList)
+	BOOST_FOREACH(const auto & building, buildList)
 	{
 		if(t->hasBuilt(building))
 			continue;
@@ -1335,9 +1335,9 @@ bool VCAI::tryBuildAnyStructure(const CGTownInstance * t, std::vector<int> build
 	return false; //Can't build anything
 }
 
-bool VCAI::tryBuildNextStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays)
+bool VCAI::tryBuildNextStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays)
 {
-	BOOST_FOREACH(int building, buildList)
+	BOOST_FOREACH(const auto & building, buildList)
 	{
 		if(t->hasBuilt(building))
 			continue;
@@ -1354,37 +1354,39 @@ void VCAI::buildStructure(const CGTownInstance * t)
 	//Possible - allow "locking" on specific building (build prerequisites and then building itself)
 
 	//Set of buildings for different goals. Does not include any prerequisites.
-	const int essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
-	const int goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
-	const int unitsSource[] = { 30, 31, 32, 33, 34, 35, 36};
-	const int unitsUpgrade[] = { 37, 38, 39, 40, 41, 42, 43};
-	const int unitGrowth[] = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE, BuildingID::HORDE_1,
+	const BuildingID essential[] = {BuildingID::TAVERN, BuildingID::TOWN_HALL};
+	const BuildingID goldSource[] = {BuildingID::TOWN_HALL, BuildingID::CITY_HALL, BuildingID::CAPITOL};
+	const BuildingID unitsSource[] = { BuildingID::DWELL_LVL_1, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3,
+		BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7};
+	const BuildingID unitsUpgrade[] = { BuildingID::DWELL_LVL_1_UP, BuildingID::DWELL_LVL_2_UP, BuildingID::DWELL_LVL_3_UP,
+		BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP};
+	const BuildingID unitGrowth[] = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE, BuildingID::HORDE_1,
 		BuildingID::HORDE_1_UPGR, BuildingID::HORDE_2, BuildingID::HORDE_2_UPGR};
-	const int spells[] = {BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3,
+	const BuildingID spells[] = {BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3,
 		BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5};
-	const int extra[] = {BuildingID::RESOURCE_SILO, BuildingID::SPECIAL_1, BuildingID::SPECIAL_2, BuildingID::SPECIAL_3,
+	const BuildingID extra[] = {BuildingID::RESOURCE_SILO, BuildingID::SPECIAL_1, BuildingID::SPECIAL_2, BuildingID::SPECIAL_3,
 		BuildingID::SPECIAL_4, BuildingID::SHIPYARD}; // all remaining buildings
 
 	TResources currentRes = cb->getResourceAmount();
 	TResources income = estimateIncome();
 
-	if (tryBuildAnyStructure(t, std::vector<int>(essential, essential + ARRAY_COUNT(essential))))
+	if (tryBuildAnyStructure(t, std::vector<BuildingID>(essential, essential + ARRAY_COUNT(essential))))
 		return;
 
 	//we're running out of gold - try to build something gold-producing. Multiplier can be tweaked, 6 is minimum due to buildings costs
 	if (currentRes[Res::GOLD] < income[Res::GOLD] * 6)
-		if (tryBuildNextStructure(t, std::vector<int>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
+		if (tryBuildNextStructure(t, std::vector<BuildingID>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
 			return;
 
 	if (cb->getDate(Date::DAY_OF_WEEK) > 6)// last 2 days of week - try to focus on growth
 	{
-		if (tryBuildNextStructure(t, std::vector<int>(unitGrowth, unitGrowth + ARRAY_COUNT(unitGrowth)), 2))
+		if (tryBuildNextStructure(t, std::vector<BuildingID>(unitGrowth, unitGrowth + ARRAY_COUNT(unitGrowth)), 2))
 			return;
 	}
 
 	// first in-game week or second half of any week: try build dwellings
 	if (cb->getDate(Date::DAY) < 7 || cb->getDate(Date::DAY_OF_WEEK) > 3)
-		if (tryBuildAnyStructure(t, std::vector<int>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(Date::DAY_OF_WEEK)))
+		if (tryBuildAnyStructure(t, std::vector<BuildingID>(unitsSource, unitsSource + ARRAY_COUNT(unitsSource)), 8 - cb->getDate(Date::DAY_OF_WEEK)))
 			return;
 
 	//try to upgrade dwelling
@@ -1398,11 +1400,11 @@ void VCAI::buildStructure(const CGTownInstance * t)
 	}
 
 	//remaining tasks
-	if (tryBuildNextStructure(t, std::vector<int>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
+	if (tryBuildNextStructure(t, std::vector<BuildingID>(goldSource, goldSource + ARRAY_COUNT(goldSource))))
 		return;
-	if (tryBuildNextStructure(t, std::vector<int>(spells, spells + ARRAY_COUNT(spells))))
+	if (tryBuildNextStructure(t, std::vector<BuildingID>(spells, spells + ARRAY_COUNT(spells))))
 		return;
-	if (tryBuildAnyStructure(t, std::vector<int>(extra, extra + ARRAY_COUNT(extra))))
+	if (tryBuildAnyStructure(t, std::vector<BuildingID>(extra, extra + ARRAY_COUNT(extra))))
 		return;
 }
 
@@ -1928,19 +1930,19 @@ void VCAI::tryRealize(CGoal g)
 			{
 				BOOST_FOREACH(const CGTownInstance *t, cb->getTownsInfo())
 				{
-					switch(cb->canBuildStructure(t, g.bid))
+					switch(cb->canBuildStructure(t, BuildingID(g.bid)))
 					{
 					case EBuildingState::ALLOWED:
-						cb->buildBuilding(t, g.bid);
+						cb->buildBuilding(t, BuildingID(g.bid));
 						return;
 					default:
 						break;
 					}
 				}
 			}
-			else if(cb->canBuildStructure(t, g.bid) == EBuildingState::ALLOWED)
+			else if(cb->canBuildStructure(t, BuildingID(g.bid)) == EBuildingState::ALLOWED)
 			{
-				cb->buildBuilding(t, g.bid);
+				cb->buildBuilding(t, BuildingID(g.bid));
 				return;
 			}
 			throw cannotFulfillGoalException("Cannot build a given structure!");
@@ -3204,7 +3206,7 @@ TSubgoal CGoal::whatToDoToAchieve()
 					auto creatures = t->town->creatures[creature->level];
 					int upgradeNumber = std::find(creatures.begin(), creatures.end(), creature->idNumber) - creatures.begin();
 
-					int bid = BuildingID::DWELL_FIRST + creature->level + upgradeNumber * GameConstants::CREATURES_PER_TOWN;
+					BuildingID bid(BuildingID::DWELL_FIRST + creature->level + upgradeNumber * GameConstants::CREATURES_PER_TOWN);
 					if (t->hasBuilt(bid)) //this assumes only creatures with dwellings are assigned to faction
 					{
 						dwellings.push_back(t);

+ 4 - 4
AI/VCAI/VCAI.h

@@ -241,11 +241,11 @@ class VCAI : public CAdventureAI
 	//internal methods for town development
 
 	//try build an unbuilt structure in maxDays at most (0 = indefinite)
-	bool tryBuildStructure(const CGTownInstance * t, int building, unsigned int maxDays=0);
+	bool tryBuildStructure(const CGTownInstance * t, BuildingID building, unsigned int maxDays=0);
 	//try build ANY unbuilt structure
-	bool tryBuildAnyStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays=0);
+	bool tryBuildAnyStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=0);
 	//try build first unbuilt structure
-	bool tryBuildNextStructure(const CGTownInstance * t, std::vector<int> buildList, unsigned int maxDays=0);
+	bool tryBuildNextStructure(const CGTownInstance * t, std::vector<BuildingID> buildList, unsigned int maxDays=0);
 
 public:
 	friend class FuzzyHelper;
@@ -337,7 +337,7 @@ public:
 	virtual void heroSecondarySkillChanged(const CGHeroInstance * hero, int which, int val) OVERRIDE;
 	virtual void battleResultsApplied() OVERRIDE;
 	virtual void objectPropertyChanged(const SetObjectProperty * sop) OVERRIDE;
-	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what) OVERRIDE;
+	virtual void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) OVERRIDE;
 	virtual void heroBonusChanged(const CGHeroInstance *hero, const Bonus &bonus, bool gain) OVERRIDE;
 	virtual void showMarketWindow(const IMarket *market, const CGHeroInstance *visitor) OVERRIDE;
 

+ 1 - 1
CCallback.cpp

@@ -164,7 +164,7 @@ bool CCallback::assembleArtifacts (const CGHeroInstance * hero, ArtifactPosition
 	return true;
 }
 
-bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
+bool CCallback::buildBuilding(const CGTownInstance *town, BuildingID buildingID)
 {
 	if(town->tempOwner!=player)
 		return false;

+ 2 - 2
CCallback.h

@@ -49,7 +49,7 @@ public:
 
 	//town
 	virtual void recruitHero(const CGObjectInstance *townOrTavern, const CGHeroInstance *hero)=0;
-	virtual bool buildBuilding(const CGTownInstance *town, si32 buildingID)=0;
+	virtual bool buildBuilding(const CGTownInstance *town, BuildingID buildingID)=0;
 	virtual void recruitCreatures(const CGObjectInstance *obj, CreatureID ID, ui32 amount, si32 level=-1)=0;
 	virtual bool upgradeCreature(const CArmedInstance *obj, int stackPos, CreatureID newID=CreatureID::NONE)=0; //if newID==-1 then best possible upgrade will be made
 	virtual void swapGarrisonHero(const CGTownInstance *town)=0;
@@ -127,7 +127,7 @@ public:
 	//bool moveArtifact(const CGHeroInstance * hero, ui16 src, const CStackInstance * stack, ui16 dest); // TODO: unify classes
 	//bool moveArtifact(const CStackInstance * stack, ui16 src , const CGHeroInstance * hero, ui16 dest); // TODO: unify classes
 	bool assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition::ArtifactPosition artifactSlot, bool assemble, ui32 assembleTo);
-	bool buildBuilding(const CGTownInstance *town, si32 buildingID);
+	bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) OVERRIDE;
 	void recruitCreatures(const CGObjectInstance *obj, CreatureID ID, ui32 amount, si32 level=-1);
 	bool dismissCreature(const CArmedInstance *obj, int stackPos);
 	bool upgradeCreature(const CArmedInstance *obj, int stackPos, CreatureID newID=CreatureID::NONE) OVERRIDE;

+ 23 - 23
client/CCastleInterface.cpp

@@ -105,7 +105,7 @@ void CBuildingRect::clickRight(tribool down, bool previousState)
 		return;
 	if( !CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image
 	{
-		int bid = str->building->bid;
+		BuildingID bid = str->building->bid;
 		const CBuilding *bld = town->town->buildings[bid];
 		if (bid < BuildingID::DWELL_FIRST)
 		{
@@ -516,10 +516,10 @@ CCastleBuildings::~CCastleBuildings()
 {
 }
 
-void CCastleBuildings::addBuilding(int building)
+void CCastleBuildings::addBuilding(BuildingID building)
 {
 	//FIXME: implement faster method without complete recreation of town
-	int base = town->town->buildings[building]->getBase();
+	BuildingID base = town->town->buildings[building]->getBase();
 
 	recreate();
 
@@ -539,7 +539,7 @@ void CCastleBuildings::addBuilding(int building)
 	}
 }
 
-void CCastleBuildings::removeBuilding(int building)
+void CCastleBuildings::removeBuilding(BuildingID building)
 {
 	//FIXME: implement faster method without complete recreation of town
 	recreate();
@@ -568,7 +568,7 @@ const CGHeroInstance* CCastleBuildings::getHero()
 	return NULL;
 }
 
-void CCastleBuildings::buildingClicked(int building)
+void CCastleBuildings::buildingClicked(BuildingID building)
 {
 	tlog5<<"You've clicked on "<<building<<std::endl;
 	const CBuilding *b = town->town->buildings.find(building)->second;
@@ -715,7 +715,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID)
 	const CGHeroInstance *hero = town->visitingHero;
 	if(!hero)
 	{
-		LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(16)->second->Name()));
+		LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(BuildingID::BLACKSMITH)->second->Name()));
 		return;
 	}
 	int price = CGI->arth->artifacts[artifactID]->price;
@@ -723,7 +723,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID)
 	GH.pushInt(new CBlacksmithDialog(possible, CArtHandler::machineIDToCreature(artifactID), artifactID, hero->id));
 }
 
-void CCastleBuildings::enterBuilding(int building)
+void CCastleBuildings::enterBuilding(BuildingID building)
 {
 	std::vector<CComponent*> comps(1, new CComponent(CComponent::building, town->subID, building));
 
@@ -760,7 +760,7 @@ void CCastleBuildings::enterDwelling(int level)
 	GH.pushInt(new CRecruitmentWindow(town, level, town, boost::bind(&CCallback::recruitCreatures,LOCPLINT->cb,town,_1,_2,level), -87));
 }
 
-void CCastleBuildings::enterFountain(int building)
+void CCastleBuildings::enterFountain(BuildingID building)
 {
 	std::vector<CComponent*> comps(1, new CComponent(CComponent::building,town->subID,building));
 
@@ -923,7 +923,7 @@ void CCastleInterface::townChange()
 	GH.pushInt(new CCastleInterface(dest, town));
 }
 
-void CCastleInterface::addBuilding(int bid)
+void CCastleInterface::addBuilding(BuildingID bid)
 {
 	deactivate();
 	builds->addBuilding(bid);
@@ -931,7 +931,7 @@ void CCastleInterface::addBuilding(int bid)
 	activate();
 }
 
-void CCastleInterface::removeBuilding(int bid)
+void CCastleInterface::removeBuilding(BuildingID bid)
 {
 	deactivate();
 	builds->removeBuilding(bid);
@@ -1101,7 +1101,7 @@ CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance* Town, bool townHa
 			return;
 		picture = new CAnimImage("ITMCL.DEF", town->fortLevel()-1);
 	}
-	building = town->town->buildings[buildID];
+	building = town->town->buildings[BuildingID(buildID)];
 	pos = picture->pos;
 }
 
@@ -1285,7 +1285,7 @@ CHallInterface::CHallInterface(const CGTownInstance *Town):
 	Rect barRect(5, 556, 740, 18);
 	statusBar = new CGStatusBar(new CPicture(*background, barRect, 5, 556, false));
 
-	title = new CLabel(399, 12, FONT_MEDIUM, CENTER, Colors::WHITE, town->town->buildings[town->hallLevel()+BuildingID::VILLAGE_HALL]->Name());
+	title = new CLabel(399, 12, FONT_MEDIUM, CENTER, Colors::WHITE, town->town->buildings[BuildingID(town->hallLevel()+BuildingID::VILLAGE_HALL)]->Name());
 	exit = new CAdventureMapButton(CGI->generaltexth->hcommands[8], "", 
 	           boost::bind(&CHallInterface::close,this), 748, 556, "TPMAGE1.DEF", SDLK_RETURN);
 	exit->assignedKeys.insert(SDLK_ESCAPE);
@@ -1299,7 +1299,7 @@ CHallInterface::CHallInterface(const CGTownInstance *Town):
 			const CBuilding *building = NULL;
 			for(size_t item=0; item<boxList[row][col].size(); item++)//we are looking for the first not build structure
 			{
-				int buildingID = boxList[row][col][item];
+				auto buildingID = boxList[row][col][item];
 				building = town->town->buildings[buildingID];
 
 				if(!vstd::contains(town->builtBuildings,buildingID))
@@ -1335,13 +1335,13 @@ std::string CBuildWindow::getTextForState(int state)
 	case 8:
 		{
 			ret = CGI->generaltexth->allTexts[52];
-			std::set<int> reqs= LOCPLINT->cb->getBuildingRequiments(town, building->bid);
+			std::set<BuildingID> reqs= LOCPLINT->cb->getBuildingRequiments(town, building->bid);
 
-			for(std::set<int>::iterator i=reqs.begin();i!=reqs.end();i++)
+			BOOST_FOREACH(const auto & i, reqs)
 			{
-				if (vstd::contains(town->builtBuildings, *i))
+				if (vstd::contains(town->builtBuildings, i))
 					continue;//skipping constructed buildings
-				ret+= town->town->buildings[*i]->Name() + ", ";
+				ret+= town->town->buildings[i]->Name() + ", ";
 			}
 			ret.erase(ret.size()-2);
 		}
@@ -1413,7 +1413,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
 	if (fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty())
 		fortSize--;
 	
-	const CBuilding *fortBuilding = town->town->buildings[town->fortLevel()+6];
+	const CBuilding *fortBuilding = town->town->buildings[BuildingID(town->fortLevel()+6)];
 	title = new CLabel(400, 12, FONT_BIG, CENTER, Colors::WHITE, fortBuilding->Name());
 	
 	std::string text = boost::str(boost::format(CGI->generaltexth->fcommands[6]) % fortBuilding->Name());
@@ -1432,16 +1432,16 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
 	
 	for (ui32 i=0; i<fortSize; i++)
 	{
-		int buildingID;
+		BuildingID buildingID;
 		if (fortSize == GameConstants::CREATURES_PER_TOWN)
 		{
 			if (vstd::contains(town->builtBuildings, BuildingID::DWELL_UP_FIRST+i))
-				buildingID = BuildingID::DWELL_UP_FIRST+i;
+				buildingID = BuildingID(BuildingID::DWELL_UP_FIRST+i);
 			else
-				buildingID = BuildingID::DWELL_FIRST+i;
+				buildingID = BuildingID(BuildingID::DWELL_FIRST+i);
 		}
 		else
-			buildingID = 22;
+			buildingID = BuildingID::SPECIAL_3;
 		recAreas.push_back(new RecruitArea(positions[i].x, positions[i].y, town, buildingID, i));
 	}
 
@@ -1504,7 +1504,7 @@ void LabeledValue::hover(bool on)
 	}
 }
 
-CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *Town, int buildingID, int Level):
+CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *Town, BuildingID buildingID, int Level):
 	town(Town),
 	level(Level),
 	availableCount(NULL)

+ 9 - 9
client/CCastleInterface.h

@@ -115,7 +115,7 @@ class CCastleBuildings : public CIntObject
 {
 	CPicture *background;
 	//List of buildings and structures that can represent them
-	std::map< si32, std::vector<const CStructure*> > groups;
+	std::map< BuildingID, std::vector<const CStructure*> > groups;
 	// actual IntObject's visible on screen
 	std::vector< CBuildingRect * > buildings;
 
@@ -124,9 +124,9 @@ class CCastleBuildings : public CIntObject
 	const CGHeroInstance* getHero();//Select hero for buildings usage
 
 	void enterBlacksmith(ArtifactID artifactID);//support for blacksmith + ballista yard
-	void enterBuilding(int building);//for buildings with simple description + pic left-click messages
+	void enterBuilding(BuildingID building);//for buildings with simple description + pic left-click messages
 	void enterCastleGate();
-	void enterFountain(int building);//Rampart's fountains
+	void enterFountain(BuildingID building);//Rampart's fountains
 	void enterMagesGuild();
 	void enterTownHall();
 
@@ -142,9 +142,9 @@ public:
 
 	void enterDwelling(int level);
 
-	void buildingClicked(int building);
-	void addBuilding(int building);
-	void removeBuilding(int building);//FIXME: not tested!!!
+	void buildingClicked(BuildingID building);
+	void addBuilding(BuildingID building);
+	void removeBuilding(BuildingID building);//FIXME: not tested!!!
 	
 	void show(SDL_Surface * to);
 	void showAll(SDL_Surface * to);
@@ -224,8 +224,8 @@ public:
 	void townChange();
 	void keyPressed(const SDL_KeyboardEvent & key);
 	void close();
-	void addBuilding(int bid);
-	void removeBuilding(int bid);
+	void addBuilding(BuildingID bid);
+	void removeBuilding(BuildingID bid);
 	void recreateIcons();
 };
 
@@ -312,7 +312,7 @@ class CFortScreen : public CWindowObject
 		CCreaturePic *creatureAnim;
 
 	public:
-		RecruitArea(int posX, int posY, const CGTownInstance *town, int buildingID, int level);
+		RecruitArea(int posX, int posY, const CGTownInstance *town, BuildingID buildingID, int level);
 		
 		void creaturesChanged();
 		void hover(bool on);

+ 4 - 2
client/CPlayerInterface.cpp

@@ -563,12 +563,14 @@ void CPlayerInterface::garrisonChanged( const CGObjectInstance * obj)
 	garrisonsChanged(std::vector<const CGObjectInstance *>(1, obj));
 }
 
-void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID, int what) //what: 1 - built, 2 - demolished
+void CPlayerInterface::buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) //what: 1 - built, 2 - demolished
 {
 	EVENT_HANDLER_CALLED_BY_CLIENT;
 	switch (buildingID)
 	{
-	case 7: case 8: case 9: case 10: case 11: case 12: case 13: case 15:
+	case BuildingID::FORT: case BuildingID::CITADEL: case BuildingID::CASTLE:
+	case BuildingID::VILLAGE_HALL: case BuildingID::TOWN_HALL: case BuildingID::CITY_HALL: case BuildingID::CAPITOL:
+	case BuildingID::RESOURCE_SILO:
 		updateInfo(town);
 		break;
 	}

+ 1 - 1
client/CPlayerInterface.h

@@ -128,7 +128,7 @@ public:
 	int getLastIndex(std::string namePrefix);
 
 	//overridden funcs from CGameInterface
-	void buildChanged(const CGTownInstance *town, int buildingID, int what) OVERRIDE; //what: 1 - built, 2 - demolished
+	void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what) OVERRIDE; //what: 1 - built, 2 - demolished
 	void stackChagedCount(const StackLocation &location, const TQuantity &change, bool isAbsolute) OVERRIDE; //if absolute, change is the new count; otherwise count was modified by adding change
 	void stackChangedType(const StackLocation &location, const CCreature &newType) OVERRIDE; //used eg. when upgrading creatures
 	void stacksErased(const StackLocation &location) OVERRIDE; //stack removed from previously filled slot

+ 1 - 1
client/CPreGame.cpp

@@ -3443,7 +3443,7 @@ void CBonusSelection::updateBonusSelection()
 					}
 					assert(faction != -1);
 
-					int buildID = CBuildingHandler::campToERMU(bonDescs[i].info1, faction, std::set<si32>());
+					BuildingID buildID = CBuildingHandler::campToERMU(bonDescs[i].info1, faction, std::set<BuildingID>());
 					picName = graphics->ERMUtoPicture[faction][buildID];
 					picNumber = -1;
 

+ 4 - 4
client/GUIClasses.cpp

@@ -964,7 +964,7 @@ std::string CComponent::getDescription()
 	case spell:      return CGI->spellh->spells[subtype]->descriptions[val];
 	case morale:     return CGI->generaltexth->heroscrn[ 4 - (val>0) + (val<0)];
 	case luck:       return CGI->generaltexth->heroscrn[ 7 - (val>0) + (val<0)];
-	case building:   return CGI->townh->towns[subtype].buildings[val]->Description();
+	case building:   return CGI->townh->towns[subtype].buildings[BuildingID(val)]->Description();
 	case hero:       return CGI->heroh->heroes[subtype]->name;
 	case flag:       return "";
 	}
@@ -996,7 +996,7 @@ std::string CComponent::getSubtitleInternal()
 	case spell:      return CGI->spellh->spells[subtype]->name;
 	case morale:     return "";
 	case luck:       return "";
-	case building:   return CGI->townh->towns[subtype].buildings[val]->Name();
+	case building:   return CGI->townh->towns[subtype].buildings[BuildingID(val)]->Name();
 	case hero:       return CGI->heroh->heroes[subtype]->name;
 	case flag:       return CGI->generaltexth->capColors[subtype];
 	}
@@ -4497,9 +4497,9 @@ void LRClickableAreaOpenTown::clickLeft(tribool down, bool previousState)
 		{
 		LOCPLINT->openTownWindow(town);
 		if ( type == 2 )
-			LOCPLINT->castleInt->builds->buildingClicked(10);
+			LOCPLINT->castleInt->builds->buildingClicked(BuildingID::VILLAGE_HALL);
 		else if ( type == 3 && town->fortLevel() )
-			LOCPLINT->castleInt->builds->buildingClicked(7);
+			LOCPLINT->castleInt->builds->buildingClicked(BuildingID::FORT);
 		}
 }
 

+ 4 - 4
client/NetPacksClient.cpp

@@ -404,9 +404,9 @@ void TryMoveHero::applyCl( CClient *cl )
 void NewStructures::applyCl( CClient *cl )
 {
 	CGTownInstance *town = GS(cl)->getTown(tid);
-	BOOST_FOREACH(si32 id, bid)
+	BOOST_FOREACH(const auto & id, bid)
 	{
-		if(id== BuildingID::CAPITOL) //fort or capitol
+		if(id == BuildingID::CAPITOL) //fort or capitol
 		{
 			town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->capitols[town->subID].get());
 		}
@@ -421,9 +421,9 @@ void NewStructures::applyCl( CClient *cl )
 void RazeStructures::applyCl (CClient *cl)
 {
 	CGTownInstance *town = GS(cl)->getTown(tid);
-	BOOST_FOREACH(si32 id, bid)
+	BOOST_FOREACH(const auto & id, bid)
 	{
-		if (id == 13) //fort or capitol
+		if (id == BuildingID::CAPITOL) //fort or capitol
 		{
 			town->defInfo = const_cast<CGDefInfo*>(CGI->dobjinfo->gobjs[Obj::TOWN][town->subID].get());
 		}

+ 9 - 10
lib/CBuildingHandler.cpp

@@ -1,7 +1,6 @@
 #include "StdInc.h"
 #include "CBuildingHandler.h"
 
-#include "GameConstants.h"
 
 /*
  * CBuildingHandler.cpp, part of VCMI engine
@@ -13,7 +12,7 @@
  *
  */
 
-int CBuildingHandler::campToERMU( int camp, int townType, std::set<si32> builtBuildings )
+BuildingID CBuildingHandler::campToERMU( int camp, int townType, std::set<BuildingID> builtBuildings )
 {
 	using namespace boost::assign;
 	static const std::vector<int> campToERMU = list_of(11)(12)(13)(7)(8)(9)(5)(16)(14)(15)(-1)(0)(1)(2)(3)(4)
@@ -21,7 +20,7 @@ int CBuildingHandler::campToERMU( int camp, int townType, std::set<si32> builtBu
 		; //creature generators with banks - handled separately
 	if (camp < campToERMU.size())
 	{
-		return campToERMU[camp];
+		return BuildingID(campToERMU[camp]);
 	}
 
 	static const std::vector<int> hordeLvlsPerTType[GameConstants::F_NUMBER] = {list_of(2), list_of(1), list_of(1)(4), list_of(0)(2),
@@ -31,10 +30,10 @@ int CBuildingHandler::campToERMU( int camp, int townType, std::set<si32> builtBu
 	for (int i=0; i<7; ++i)
 	{
 		if(camp == curPos) //non-upgraded
-			return 30 + i;
+			return BuildingID(30 + i);
 		curPos++;
 		if(camp == curPos) //upgraded
-			return 37 + i;
+			return BuildingID(37 + i);
 		curPos++;
 		//horde building
 		if (vstd::contains(hordeLvlsPerTType[townType], i))
@@ -44,18 +43,18 @@ int CBuildingHandler::campToERMU( int camp, int townType, std::set<si32> builtBu
 				if (hordeLvlsPerTType[townType][0] == i)
 				{
 					if(vstd::contains(builtBuildings, 37 + hordeLvlsPerTType[townType][0])) //if upgraded dwelling is built
-						return 19;
+						return BuildingID::HORDE_1_UPGR;
 					else //upgraded dwelling not presents
-						return 18;
+						return BuildingID::HORDE_1;
 				}
 				else
 				{
 					if(hordeLvlsPerTType[townType].size() > 1)
 					{
 						if(vstd::contains(builtBuildings, 37 + hordeLvlsPerTType[townType][1])) //if upgraded dwelling is built
-							return 25;
+							return BuildingID::HORDE_2_UPGR;
 						else //upgraded dwelling not presents
-							return 24;
+							return BuildingID::HORDE_2;
 					}
 				}
 			}
@@ -64,6 +63,6 @@ int CBuildingHandler::campToERMU( int camp, int townType, std::set<si32> builtBu
 
 	}
 	assert(0);
-	return -1; //not found
+	return BuildingID::NONE; //not found
 }
 

+ 3 - 1
lib/CBuildingHandler.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#include "GameConstants.h"
+
 /*
  * CBuildingHandler.h, part of VCMI engine
  *
@@ -13,5 +15,5 @@
 class DLL_LINKAGE CBuildingHandler
 {
 public:
-	static int campToERMU(int camp, int townType, std::set<si32> builtBuildings);
+	static BuildingID campToERMU(int camp, int townType, std::set<BuildingID> builtBuildings);
 };

+ 32 - 31
lib/CGameState.cpp

@@ -1442,6 +1442,33 @@ void CGameState::init(StartInfo * si)
 	}
 	/****************************TOWNS************************************************/
 	tlog4 << "\tTowns";
+
+	//campaign bonuses for towns
+	if (scenarioOps->mode == StartInfo::CAMPAIGN)
+	{
+		auto chosenBonus = scenarioOps->campState->getBonusForCurrentMap();
+
+		if (chosenBonus.is_initialized() && chosenBonus->type == CScenarioTravel::STravelBonus::BUILDING)
+		{
+			for (int g=0; g<map->towns.size(); ++g)
+			{
+				PlayerState * owner = getPlayer(map->towns[g]->getOwner());
+				if (owner)
+				{
+					PlayerInfo & pi = map->players[owner->color];
+
+					if (owner->human && //human-owned
+						map->towns[g]->pos == pi.posOfMainTown + int3(2, 0, 0))
+					{
+						map->towns[g]->builtBuildings.insert(
+							CBuildingHandler::campToERMU(chosenBonus->info1, map->towns[g]->town->typeID, map->towns[g]->builtBuildings));
+						break;
+					}
+				}
+			}
+		}
+	}
+
 	CGTownInstance::universitySkills.clear();
 	for ( int i=0; i<4; i++)
 		CGTownInstance::universitySkills.push_back(14+i);//skills for university
@@ -1455,14 +1482,14 @@ void CGameState::init(StartInfo * si)
 			vti->name = vti->town->names[ran()%vti->town->names.size()];
 
 		//init buildings
-		if(vti->builtBuildings.find(-50)!=vti->builtBuildings.end()) //give standard set of buildings
+		if(vstd::contains(vti->builtBuildings, BuildingID::DEFAULT)) //give standard set of buildings
 		{
-			vti->builtBuildings.erase(-50);
+			vti->builtBuildings.erase(BuildingID::DEFAULT);
 			vti->builtBuildings.insert(BuildingID::VILLAGE_HALL);
 			vti->builtBuildings.insert(BuildingID::TAVERN);
 			vti->builtBuildings.insert(BuildingID::DWELL_FIRST);
 			if(ran()%2)
-				vti->builtBuildings.insert(BuildingID::DWELL_FIRST+1);
+				vti->builtBuildings.insert(BuildingID::DWELL_LVL_2);
 		}
 
 		if (vstd::contains(vti->builtBuildings, BuildingID::SHIPYARD) && vti->state()==IBoatGenerator::TILE_BLOCKED)
@@ -1472,7 +1499,7 @@ void CGameState::init(StartInfo * si)
 		for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++)
 			if (vstd::contains(vti->builtBuildings,(-31-i))) //if we have horde for this level
 			{
-				vti->builtBuildings.erase(-31-i);//remove old ID
+				vti->builtBuildings.erase(BuildingID(-31-i));//remove old ID
 				if (vti->town->hordeLvl[0] == i)//if town first horde is this one
 				{
 					vti->builtBuildings.insert(BuildingID::HORDE_1);//add it
@@ -1493,7 +1520,7 @@ void CGameState::init(StartInfo * si)
 			for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++)
 				if (vstd::contains(ev->buildings,(-31-i))) //if we have horde for this level
 				{
-					ev->buildings.erase(-31-i);
+					ev->buildings.erase(BuildingID(-31-i));
 					if (vti->town->hordeLvl[0] == i)
 						ev->buildings.insert(BuildingID::HORDE_1);
 					if (vti->town->hordeLvl[1] == i)
@@ -1542,32 +1569,6 @@ void CGameState::init(StartInfo * si)
 			getPlayer(vti->getOwner())->towns.push_back(vti);
 	}
 
-	//campaign bonuses for towns
-	if (scenarioOps->mode == StartInfo::CAMPAIGN)
-	{
-		auto chosenBonus = scenarioOps->campState->getBonusForCurrentMap();
-
-		if (chosenBonus.is_initialized() && chosenBonus->type == CScenarioTravel::STravelBonus::BUILDING)
-		{
-			for (int g=0; g<map->towns.size(); ++g)
-			{
-				PlayerState * owner = getPlayer(map->towns[g]->getOwner());
-				if (owner)
-				{
-					PlayerInfo & pi = map->players[owner->color];
-
-					if (owner->human && //human-owned
-						map->towns[g]->pos == pi.posOfMainTown + int3(2, 0, 0))
-					{
-						map->towns[g]->builtBuildings.insert(
-							CBuildingHandler::campToERMU(chosenBonus->info1, map->towns[g]->town->typeID, map->towns[g]->builtBuildings));
-						break;
-					}
-				}
-			}
-		}
-
-	}
 	tlog4 << "\tObject initialization";
 	objCaller->preInit();
 	BOOST_FOREACH(CGObjectInstance *obj, map->objects)

+ 13 - 13
lib/CObjectHandler.cpp

@@ -1938,7 +1938,7 @@ int CGTownInstance::creatureDwellingLevel(int dwelling) const
 		return -1;
 	for (int i=0; ; i++)
 	{
-		if (!hasBuilt(BuildingID::DWELL_FIRST+dwelling+i*GameConstants::CREATURES_PER_TOWN))
+		if (!hasBuilt(BuildingID(BuildingID::DWELL_FIRST+dwelling+i*GameConstants::CREATURES_PER_TOWN)))
 			return i-1;
 	}
 }
@@ -1957,7 +1957,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
 
 	if (level<0 || level >=GameConstants::CREATURES_PER_TOWN)
 		return ret;
-	if (!hasBuilt(BuildingID::DWELL_FIRST+level))
+	if (!hasBuilt(BuildingID(BuildingID::DWELL_FIRST+level)))
 		return ret; //no dwelling
 
 	const CCreature *creature = VLC->creh->creatures[creatures[level].second.back()];
@@ -2132,15 +2132,15 @@ void CGTownInstance::initObj()
 	switch (subID)
 	{ //add new visitable objects
 		case 0:
-			bonusingBuildings.push_back (new COPWBonus(21, this)); //Stables
+			bonusingBuildings.push_back (new COPWBonus(BuildingID::STABLES, this));
 			break;
 		case 5:
-			bonusingBuildings.push_back (new COPWBonus(21, this)); //Vortex
+			bonusingBuildings.push_back (new COPWBonus(BuildingID::MANA_VORTEX, this));
 		case 2: case 3: case 6:
-			bonusingBuildings.push_back (new CTownBonus(23, this));
+			bonusingBuildings.push_back (new CTownBonus(BuildingID::SPECIAL_4, this));
 			break;
 		case 7:
-			bonusingBuildings.push_back (new CTownBonus(17, this));
+			bonusingBuildings.push_back (new CTownBonus(BuildingID::SPECIAL_1, this));
 			break;
 	}
 	//add special bonuses from buildings
@@ -2272,7 +2272,7 @@ void CGTownInstance::removeCapitols (ui8 owner) const
 			{
 				RazeStructures rs;
 				rs.tid = id;
-				rs.bid.insert(13);
+				rs.bid.insert(BuildingID::CAPITOL);
 				rs.destroyed = destroyed;
 				cb->sendAndApply(&rs);
 				return;
@@ -2426,12 +2426,12 @@ void CGTownInstance::recreateBuildingsBonuses()
 	}
 }
 
-bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, int subtype /*= -1*/)
+bool CGTownInstance::addBonusIfBuilt(BuildingID building, int type, int val, int subtype /*= -1*/)
 {
 	return addBonusIfBuilt(building, type, val, TPropagatorPtr(), subtype);
 }
 
-bool CGTownInstance::addBonusIfBuilt(int building, int type, int val, TPropagatorPtr prop, int subtype /*= -1*/)
+bool CGTownInstance::addBonusIfBuilt(BuildingID building, int type, int val, TPropagatorPtr prop, int subtype /*= -1*/)
 {
 	if(hasBuilt(building))
 	{
@@ -2517,14 +2517,14 @@ const CArmedInstance * CGTownInstance::getUpperArmy() const
 	return this;
 }
 
-bool CGTownInstance::hasBuilt(int buildingID, int townID) const
+bool CGTownInstance::hasBuilt(BuildingID buildingID, int townID) const
 {
 	if (townID == town->typeID || townID == ETownType::ANY)
 		return hasBuilt(buildingID);
 	return false;
 }
 
-bool CGTownInstance::hasBuilt(int buildingID) const
+bool CGTownInstance::hasBuilt(BuildingID buildingID) const
 {
 	return vstd::contains(builtBuildings, buildingID);
 }
@@ -2846,7 +2846,7 @@ void CGVisitableOPH::schoolSelected(int heroID, ui32 which) const
 	cb->changePrimSkill(cb->getHero(heroID), static_cast<PrimarySkill::PrimarySkill>(base + which-1), +1); //give appropriate skill
 }
 
-COPWBonus::COPWBonus (int index, CGTownInstance *TOWN)
+COPWBonus::COPWBonus (BuildingID index, CGTownInstance *TOWN)
 {
 	ID = index;
 	town = TOWN;
@@ -2897,7 +2897,7 @@ void COPWBonus::onHeroVisit (const CGHeroInstance * h) const
 		}
 	}
 }
-CTownBonus::CTownBonus (int index, CGTownInstance *TOWN)
+CTownBonus::CTownBonus (BuildingID index, CGTownInstance *TOWN)
 {
 	ID = index;
 	town = TOWN;

+ 11 - 11
lib/CObjectHandler.h

@@ -511,7 +511,7 @@ class DLL_LINKAGE CGTownBuilding : public IObjectInterface
 {
 ///basic class for town structures handled as map objects
 public:
-	si32 ID; //from buildig list
+	BuildingID ID; //from buildig list
 	si32 id; //identifies its index on towns vector
 	CGTownInstance *town;
 
@@ -527,8 +527,8 @@ public:
 	void setProperty(ui8 what, ui32 val) override;
 	void onHeroVisit (const CGHeroInstance * h) const override;
 
-	COPWBonus (int index, CGTownInstance *TOWN);
-	COPWBonus (){ID = 0; town = NULL;};
+	COPWBonus (BuildingID index, CGTownInstance *TOWN);
+	COPWBonus (){ID = BuildingID::NONE; town = NULL;};
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CGTownBuilding&>(*this);
@@ -545,8 +545,8 @@ public:
 	void setProperty(ui8 what, ui32 val) override;
 	void onHeroVisit (const CGHeroInstance * h) const override;
 
-	CTownBonus (int index, CGTownInstance *TOWN);
-	CTownBonus (){ID = 0; town = NULL;};
+	CTownBonus (BuildingID index, CGTownInstance *TOWN);
+	CTownBonus (){ID = BuildingID::NONE; town = NULL;};
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CGTownBuilding&>(*this);
@@ -587,9 +587,9 @@ public:
 	ConstTransitivePtr<CGHeroInstance> garrisonHero, visitingHero;
 	ui32 identifier; //special identifier from h3m (only > RoE maps)
 	si32 alignment;
-	std::set<si32> forbiddenBuildings, builtBuildings;
+	std::set<BuildingID> forbiddenBuildings, builtBuildings;
 	std::vector<CGTownBuilding*> bonusingBuildings;
-	std::vector<ui32> possibleSpells, obligatorySpells;
+	std::vector<SpellID> possibleSpells, obligatorySpells;
 	std::vector<std::vector<SpellID> > spells; //spells[level] -> vector of spells, first will be available in guild
 	std::list<CCastleEvent*> events;
 	std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond);
@@ -617,8 +617,8 @@ public:
 	std::string nodeName() const override;
 	void deserializationFix();
 	void recreateBuildingsBonuses();
-	bool addBonusIfBuilt(int building, int type, int val, TPropagatorPtr prop, int subtype = -1); //returns true if building is built and bonus has been added
-	bool addBonusIfBuilt(int building, int type, int val, int subtype = -1); //convienence version of above
+	bool addBonusIfBuilt(BuildingID building, int type, int val, TPropagatorPtr prop, int subtype = -1); //returns true if building is built and bonus has been added
+	bool addBonusIfBuilt(BuildingID building, int type, int val, int subtype = -1); //convienence version of above
 	void setVisitingHero(CGHeroInstance *h);
 	void setGarrisonedHero(CGHeroInstance *h);
 	const CArmedInstance *getUpperArmy() const; //garrisoned hero if present or the town itself
@@ -649,8 +649,8 @@ public:
 	bool hasFort() const;
 	bool hasCapitol() const;
 	//checks if building is constructed and town has same subID
-	bool hasBuilt(int buildingID) const;
-	bool hasBuilt(int buildingID, int townID) const;
+	bool hasBuilt(BuildingID buildingID) const;
+	bool hasBuilt(BuildingID buildingID, int townID) const;
 	int dailyIncome() const; //calculates daily income of this town
 	int spellsAtLevel(int level, bool checkGuild) const; //levels are counted from 1 (1 - 5)
 	void removeCapitols (ui8 owner) const;

+ 13 - 13
lib/CTownHandler.cpp

@@ -31,7 +31,7 @@ const std::string & CBuilding::Description() const
 	return description;
 }
 
-CBuilding::BuildingType CBuilding::getBase() const
+BuildingID CBuilding::getBase() const
 {
 	const CBuilding * build = this;
 	while (build->upgrade >= 0)
@@ -40,7 +40,7 @@ CBuilding::BuildingType CBuilding::getBase() const
 	return build->bid;
 }
 
-si32 CBuilding::getDistance(CBuilding::BuildingType buildID) const
+si32 CBuilding::getDistance(BuildingID buildID) const
 {
 	const CBuilding * build = VLC->townh->towns[tid].buildings[buildID];
 	int distance = 0;
@@ -237,24 +237,24 @@ void CTownHandler::loadBuilding(CTown &town, const JsonNode & source)
 
 	static const std::string modes [] = {"normal", "auto", "special", "grail"};
 
-	ret->mode = boost::find(modes, source["mode"].String()) - modes;
+	ret->mode = static_cast<CBuilding::EBuildMode>(boost::find(modes, source["mode"].String()) - modes);
 
 	ret->tid = town.typeID;
-	ret->bid = source["id"].Float();
+	ret->bid = BuildingID(source["id"].Float());
 	ret->name = source["name"].String();
 	ret->description = source["description"].String();
 	ret->resources = TResources(source["cost"]);
 
 	BOOST_FOREACH(const JsonNode &building, source["requires"].Vector())
-		ret->requirements.insert(building.Float());
+		ret->requirements.insert(BuildingID(building.Float()));
 
 	if (!source["upgrades"].isNull())
 	{
-		ret->requirements.insert(source["upgrades"].Float());
-		ret->upgrade = source["upgrades"].Float();
+		ret->requirements.insert(BuildingID(source["upgrades"].Float()));
+		ret->upgrade = BuildingID(source["upgrades"].Float());
 	}
 	else
-		ret->upgrade = -1;
+		ret->upgrade = BuildingID::NONE;
 
 	town.buildings[ret->bid] = ret;
 }
@@ -278,12 +278,12 @@ void CTownHandler::loadStructure(CTown &town, const JsonNode & source)
 	}
 	else
 	{
-		ret->building = town.buildings[source["id"].Float()];
+		ret->building = town.buildings[BuildingID(source["id"].Float())];
 
 		if (source["builds"].isNull())
 			ret->buildable = ret->building;
 		else
-			ret->buildable = town.buildings[source["builds"].Float()];
+			ret->buildable = town.buildings[BuildingID(source["builds"].Float())];
 	}
 
 	ret->pos.x = source["x"].Float();
@@ -310,15 +310,15 @@ void CTownHandler::loadTownHall(CTown &town, const JsonNode & source)
 {
 	BOOST_FOREACH(const JsonNode &row, source.Vector())
 	{
-		std::vector< std::vector<int> > hallRow;
+		std::vector< std::vector<BuildingID> > hallRow;
 
 		BOOST_FOREACH(const JsonNode &box, row.Vector())
 		{
-			std::vector<int> hallBox;
+			std::vector<BuildingID> hallBox;
 
 			BOOST_FOREACH(const JsonNode &value, box.Vector())
 			{
-				hallBox.push_back(value.Float());
+				hallBox.push_back(BuildingID(value.Float()));
 			}
 			hallRow.push_back(hallBox);
 		}

+ 9 - 11
lib/CTownHandler.h

@@ -23,18 +23,17 @@ class JsonNode;
 /// contains all mechanics-related data about town structures
 class DLL_LINKAGE CBuilding
 {
-	typedef si32 BuildingType;//TODO: replace int with pointer?
 
 	std::string name;
 	std::string description;
 
 public:
-	TFaction tid;
-	si32 bid; //town ID and structure ID
+	TFaction tid; //town ID
+	BuildingID bid; //structure ID
 	TResources resources;
 
-	std::set<BuildingType> requirements; /// set of required buildings, includes upgradeOf;
-	BuildingType upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty
+	std::set<BuildingID> requirements; /// set of required buildings, includes upgradeOf;
+	BuildingID upgrade; /// indicates that building "upgrade" can be improved by this, -1 = empty
 
 	enum EBuildMode
 	{
@@ -42,17 +41,16 @@ public:
 		BUILD_AUTO,    // 1 - auto - building appears when all requirements are built
 		BUILD_SPECIAL, // 2 - special - building can not be built normally
 		BUILD_GRAIL    // 3 - grail - building reqires grail to be built
-	};
-	ui32 mode;
+	} mode;
 
 	const std::string &Name() const;
 	const std::string &Description() const;
 
 	//return base of upgrade(s) or this
-	BuildingType getBase() const;
+	BuildingID getBase() const;
 
 	// returns how many times build has to be upgraded to become build
-	si32 getDistance(BuildingType build) const;
+	si32 getDistance(BuildingID build) const;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -92,7 +90,7 @@ public:
 	// TODO: replace with pointers to CCreature
 	std::vector<std::vector<CreatureID> > creatures;
 
-	bmap<int, ConstTransitivePtr<CBuilding> > buildings;
+	bmap<BuildingID, ConstTransitivePtr<CBuilding> > buildings;
 
 	std::vector<std::string> dwellings; //defs for adventure map dwellings for new towns, [0] means tier 1 creatures etc.
 	std::vector<std::string> dwellingNames;
@@ -125,7 +123,7 @@ public:
 		std::string buildingsIcons;
 		std::string hallBackground;
 		/// vector[row][column] = list of buildings in this slot
-		std::vector< std::vector< std::vector<int> > > hallSlots;
+		std::vector< std::vector< std::vector<BuildingID> > > hallSlots;
 
 		/// list of town screen structures.
 		/// NOTE: index in vector is meaningless. Vector used instead of list for a bit faster access

+ 2 - 0
lib/GameConstants.cpp

@@ -46,6 +46,8 @@ ID_LIKE_OPERATORS(CreatureID, CreatureID::ECreatureID)
 
 ID_LIKE_OPERATORS(SpellID, SpellID::ESpellID)
 
+ID_LIKE_OPERATORS(BuildingID, BuildingID::EBuildingID)
+
 
 bmap<int, ConstTransitivePtr<CGDefInfo> > & Obj::toDefObjInfo() const
 {

+ 9 - 1
lib/GameConstants.h

@@ -196,6 +196,7 @@ public:
 	// NOTE: all building with completely configurable mechanics will be removed from list
 	enum EBuildingID
 	{
+		DEFAULT = -50,
 		NONE = -1,
 		MAGES_GUILD_1 = 0,  MAGES_GUILD_2, MAGES_GUILD_3,     MAGES_GUILD_4,   MAGES_GUILD_5,
 		TAVERN,         SHIPYARD,      FORT,              CITADEL,         CASTLE,
@@ -203,7 +204,14 @@ public:
 		RESOURCE_SILO,  BLACKSMITH,    SPECIAL_1,         HORDE_1,         HORDE_1_UPGR,
 		SHIP,           SPECIAL_2,     SPECIAL_3,         SPECIAL_4,       HORDE_2,
 		HORDE_2_UPGR,   GRAIL,         EXTRA_TOWN_HALL,   EXTRA_CITY_HALL, EXTRA_CAPITOL,
-		DWELL_FIRST=30, DWELL_LAST=36, DWELL_UP_FIRST=37, DWELL_UP_LAST=43,
+		DWELL_FIRST=30, DWELL_LVL_2, DWELL_LVL_3, DWELL_LVL_4, DWELL_LVL_5, DWELL_LVL_6, DWELL_LAST=36,
+		DWELL_UP_FIRST=37,  DWELL_LVL_2_UP, DWELL_LVL_3_UP, DWELL_LVL_4_UP, DWELL_LVL_5_UP,
+		DWELL_LVL_6_UP, DWELL_UP_LAST=43,
+
+		DWELL_LVL_1 = DWELL_FIRST,
+		DWELL_LVL_7 = DWELL_LAST,
+		DWELL_LVL_1_UP = DWELL_UP_FIRST,
+		DWELL_LVL_7_UP = DWELL_UP_LAST,
 
 		//Special buildings for towns.
 		LIGHTHOUSE  = SPECIAL_1,

+ 6 - 6
lib/IGameCallback.cpp

@@ -525,7 +525,7 @@ const TerrainTile * CGameInfoCallback::getTile( int3 tile, bool verbose) const
 	return &gs->map->getTile(tile);
 }
 
-EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
+EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTownInstance *t, BuildingID ID )
 {
 	ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", EBuildingState::TOWN_NOT_OWNED);
 
@@ -538,14 +538,14 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
 		return EBuildingState::ALREADY_PRESENT;
 
 	//can we build it?
-	if(t->forbiddenBuildings.find(ID)!=t->forbiddenBuildings.end())
+	if(vstd::contains(t->forbiddenBuildings, ID))
 		return EBuildingState::FORBIDDEN; //forbidden
 
 	//checking for requirements
-	std::set<int> reqs = getBuildingRequiments(t, ID);//getting all requirements
+	std::set<BuildingID> reqs = getBuildingRequiments(t, ID);//getting all requirements
 
 	bool notAllBuilt = false;
-	for( std::set<int>::iterator ri  =  reqs.begin(); ri != reqs.end(); ri++ )
+	for( std::set<BuildingID>::iterator ri  =  reqs.begin(); ri != reqs.end(); ri++ )
 	{
 		if(!t->hasBuilt(*ri)) //lack of requirements - cannot build
 		{
@@ -591,9 +591,9 @@ EBuildingState::EBuildingState CGameInfoCallback::canBuildStructure( const CGTow
 	return EBuildingState::ALLOWED;
 }
 
-std::set<int> CGameInfoCallback::getBuildingRequiments( const CGTownInstance *t, int ID )
+std::set<BuildingID> CGameInfoCallback::getBuildingRequiments( const CGTownInstance *t, BuildingID ID )
 {
-	ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", std::set<int>());
+	ERROR_RET_VAL_IF(!canGetFullInfo(t), "Town is not owned!", std::set<BuildingID>());
 
 	std::set<int> used;
 	used.insert(ID);

+ 3 - 3
lib/IGameCallback.h

@@ -127,8 +127,8 @@ public:
 	const CGTownInstance * getTownInfo(int val, bool mode)const; //mode = 0 -> val = player town serial; mode = 1 -> val = object id (serial)
 	std::vector<const CGHeroInstance *> getAvailableHeroes(const CGObjectInstance * townOrTavern) const; //heroes that can be recruited
 	std::string getTavernGossip(const CGObjectInstance * townOrTavern) const; 
-	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, int ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
-	std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID);
+	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID);//// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
+	std::set<BuildingID> getBuildingRequiments(const CGTownInstance *t, BuildingID ID);
 	virtual bool getTownInfo(const CGObjectInstance *town, InfoAboutTown &dest) const;
 	const CTown *getNativeTown(TPlayerColor color) const;
 
@@ -136,7 +136,7 @@ public:
 	const TeamState *getTeam(ui8 teamID) const;
 	const TeamState *getPlayerTeam(TPlayerColor color) const;
 	std::set<int> getBuildingRequiments(const CGTownInstance *t, int ID) const;
-	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, int ID) const;// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
+	EBuildingState::EBuildingState canBuildStructure(const CGTownInstance *t, BuildingID ID) const;// 0 - no more than one capitol, 1 - lack of water, 2 - forbidden, 3 - Add another level to Mage Guild, 4 - already built, 5 - cannot build, 6 - cannot afford, 7 - build, 8 - lack of requirements
 };
 
 

+ 1 - 1
lib/IGameEventsReceiver.h

@@ -72,7 +72,7 @@ public:
 class DLL_LINKAGE IGameEventsReceiver
 {
 public:
-	virtual void buildChanged(const CGTownInstance *town, int buildingID, int what){}; //what: 1 - built, 2 - demolished
+	virtual void buildChanged(const CGTownInstance *town, BuildingID buildingID, int what){}; //what: 1 - built, 2 - demolished
 
 	virtual void battleResultsApplied(){}; //called when all effects of last battle are applied
 

+ 1 - 1
lib/Mapping/CCampaignHandler.cpp

@@ -173,7 +173,7 @@ CScenarioTravel CCampaignHandler::readScenarioTravelFromMemory( const ui8 * buff
 			for (int g=0; g<numOfBonuses; ++g)
 			{
 				CScenarioTravel::STravelBonus bonus;
-				bonus.type = buffer[outIt++];
+				bonus.type = static_cast<CScenarioTravel::STravelBonus::EBonusType>(buffer[outIt++]);
 				//hero: FFFD means 'most powerful' and FFFE means 'generated'
 				switch(bonus.type)
 				{

+ 1 - 1
lib/Mapping/CCampaignHandler.h

@@ -60,7 +60,7 @@ public:
 	{
 		enum EBonusType {SPELL, MONSTER, BUILDING, ARTIFACT, SPELL_SCROLL, PRIMARY_SKILL, SECONDARY_SKILL, RESOURCE,
 			PLAYER_PREV_SCENARIO, HERO};
-		ui8 type; //uses EBonusType
+		EBonusType type; //uses EBonusType
 		si32 info1, info2, info3; //purpose depends on type
 
 		bool isBonusForHero() const;

+ 1 - 1
lib/Mapping/CMap.h

@@ -361,7 +361,7 @@ public:
 	CCastleEvent();
 
 	/** build specific buildings */
-	std::set<si32> buildings;
+	std::set<BuildingID> buildings;
 
 	/** additional creatures in i-th level dwelling */
 	std::vector<si32> creatures;

+ 8 - 8
lib/Mapping/MapFormatH3M.cpp

@@ -1908,7 +1908,7 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID)
 		}
 
 		//means that set of standard building should be included
-		nt->builtBuildings.insert(-50);
+		nt->builtBuildings.insert(BuildingID::DEFAULT);
 	}
 
 	if(map->version > EMapFormat::ROE)
@@ -1922,7 +1922,7 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID)
 				{
 					if(c == (c | static_cast<ui8>(std::pow(2., yy))))
 					{
-						nt->obligatorySpells.push_back(i * 8 + yy);
+						nt->obligatorySpells.push_back(SpellID(i * 8 + yy));
 					}
 				}
 			}
@@ -1938,7 +1938,7 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID)
 			{
 				if(c != (c | static_cast<ui8>(std::pow(2., yy))))
 				{
-					nt->possibleSpells.push_back(i * 8 + yy);
+					nt->possibleSpells.push_back(SpellID(i * 8 + yy));
 				}
 			}
 		}
@@ -1996,10 +1996,10 @@ CGTownInstance * CMapLoaderH3M::readTown(int castleID)
 	return nt;
 }
 
-std::set<si32> CMapLoaderH3M::convertBuildings(const std::set<si32> h3m, int castleID, bool addAuxiliary /*= true*/)
+std::set<BuildingID> CMapLoaderH3M::convertBuildings(const std::set<BuildingID> h3m, int castleID, bool addAuxiliary /*= true*/)
 {
-	std::map<int, int> mapa;
-	std::set<si32> ret;
+	std::map<int, BuildingID> mapa;
+	std::set<BuildingID> ret;
 
 	// Note: this file is parsed many times.
 	const JsonNode config(ResourceID("config/buildings5.json"));
@@ -2010,7 +2010,7 @@ std::set<si32> CMapLoaderH3M::convertBuildings(const std::set<si32> h3m, int cas
 
 		if (town == castleID || town == -1)
 		{
-			mapa[entry["h3"].Float()] = entry["vcmi"].Float();
+			mapa[entry["h3"].Float()] = BuildingID((si32)entry["vcmi"].Float());
 		}
 	}
 
@@ -2026,7 +2026,7 @@ std::set<si32> CMapLoaderH3M::convertBuildings(const std::set<si32> h3m, int cas
 			int level = (mapa[*i]);
 
 			//(-30)..(-36) - horde buildings (for game loading only), don't see other way to handle hordes in random towns
-			ret.insert(level - 30);
+			ret.insert(BuildingID(level - 30));
 		}
 		else
 		{

+ 1 - 1
lib/Mapping/MapFormatH3M.h

@@ -203,7 +203,7 @@ private:
 	 * @param addAuxiliary true if the village hall should be added
 	 * @return the converted buildings
 	 */
-	std::set<si32> convertBuildings(const std::set<si32> h3m, int castleID, bool addAuxiliary = true);
+	std::set<BuildingID> convertBuildings(const std::set<BuildingID> h3m, int castleID, bool addAuxiliary = true);
 
 	/**
 	 * Reads events.

+ 5 - 4
lib/NetPacks.h

@@ -644,7 +644,7 @@ struct NewStructures : public CPackForClient //504
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	si32 tid;
-	std::set<si32> bid;
+	std::set<BuildingID> bid;
 	si16 builded;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -659,7 +659,7 @@ struct RazeStructures : public CPackForClient //505
 	DLL_LINKAGE void applyGs(CGameState *gs);
 
 	si32 tid;
-	std::set<si32> bid;
+	std::set<BuildingID> bid;
 	si16 destroyed;
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -1838,8 +1838,9 @@ struct DisbandCreature : public CPackForServer
 struct BuildStructure : public CPackForServer
 {
 	BuildStructure(){};
-	BuildStructure(si32 TID, si32 BID):bid(BID),tid(TID){};
-	si32 bid, tid; //structure and town ids
+	BuildStructure(si32 TID, BuildingID BID):bid(BID),tid(TID){};
+	si32 tid; //town id
+	BuildingID bid; //structure id
 
 	bool applyGh(CGameHandler *gh);
 	template <typename Handler> void serialize(Handler &h, const int version)

+ 2 - 2
lib/NetPacksLib.cpp

@@ -414,7 +414,7 @@ void TryMoveHero::applyGs( CGameState *gs )
 DLL_LINKAGE void NewStructures::applyGs( CGameState *gs )
 {
 	CGTownInstance *t = gs->getTown(tid);
-	BOOST_FOREACH(si32 id,bid)
+	BOOST_FOREACH(const auto & id, bid)
 	{
 		t->builtBuildings.insert(id);
 	}
@@ -424,7 +424,7 @@ DLL_LINKAGE void NewStructures::applyGs( CGameState *gs )
 DLL_LINKAGE void RazeStructures::applyGs( CGameState *gs )
 {
 	CGTownInstance *t = gs->getTown(tid);
-	BOOST_FOREACH(si32 id,bid)
+	BOOST_FOREACH(const auto & id, bid)
 	{
 		t->builtBuildings.erase(id);
 	}

+ 1 - 1
lib/RMG/CMapGenerator.cpp

@@ -317,7 +317,7 @@ void CMapGenerator::genTowns()
 		town->tempOwner = owner;
 		town->defInfo = VLC->dobjinfo->gobjs[town->ID][town->subID];
 		town->builtBuildings.insert(BuildingID::FORT);
-		town->builtBuildings.insert(-50);
+		town->builtBuildings.insert(BuildingID::DEFAULT);
 		mapMgr->insertObject(town, townPos[side].x, townPos[side].y + (pos / 2) * 5, false);
 
 		// Update player info

+ 8 - 6
server/CGameHandler.cpp

@@ -2462,7 +2462,7 @@ bool CGameHandler::disbandCreature( si32 id, ui8 pos )
 	return true;
 }
 
-bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
+bool CGameHandler::buildStructure( si32 tid, BuildingID bid, bool force /*=false*/ )
 {
 	CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid].get());
 	CBuilding * b = t->town->buildings[bid];
@@ -2574,7 +2574,7 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
 	checkLossVictory(t->tempOwner);
 	return true;
 }
-bool CGameHandler::razeStructure (si32 tid, si32 bid)
+bool CGameHandler::razeStructure (si32 tid, BuildingID bid)
 {
 ///incomplete, simply erases target building
 	CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid].get());
@@ -4783,12 +4783,14 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n, std::map<
 
 			}
 
-			for(std::set<si32>::iterator i = ev->buildings.begin(); i!=ev->buildings.end();i++)
-				if ( town->hasBuilt(*i))
+			BOOST_FOREACH(auto & i, ev->buildings)
+			{
+				if ( town->hasBuilt(i))
 				{
-					buildStructure(town->id, *i, true);
-					iw.components.push_back(Component(Component::BUILDING, town->subID, *i, 0));
+					buildStructure(town->id, i, true);
+					iw.components.push_back(Component(Component::BUILDING, town->subID, i, 0));
 				}
+			}
 
 			for(si32 i=0;i<ev->creatures.size();i++) //creature growths
 			{

+ 2 - 2
server/CGameHandler.h

@@ -222,8 +222,8 @@ public:
 	bool garrisonSwap(si32 tid);
 	bool upgradeCreature( ui32 objid, ui8 pos, ui32 upgID );
 	bool recruitCreatures(si32 objid, CreatureID crid, ui32 cram, si32 level);
-	bool buildStructure(si32 tid, si32 bid, bool force=false);//force - for events: no cost, no checkings
-	bool razeStructure(si32 tid, si32 bid);
+	bool buildStructure(si32 tid, BuildingID bid, bool force=false);//force - for events: no cost, no checkings
+	bool razeStructure(si32 tid, BuildingID bid);
 	bool disbandCreature( si32 id, ui8 pos );
 	bool arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val, TPlayerColor player);
 	void save(const std::string &fname);