mirror of
				https://github.com/vcmi/vcmi.git
				synced 2025-10-31 00:07:39 +02:00 
			
		
		
		
	Merge pull request #4402 from Laserlicht/8th_creature
support for 8th creature (Factory)
This commit is contained in:
		| @@ -31,16 +31,14 @@ void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo) | ||||
| 		} | ||||
| 	} | ||||
|  | ||||
| 	BuildingID prefixes[] = {BuildingID::DWELL_UP_FIRST, BuildingID::DWELL_FIRST}; | ||||
|  | ||||
| 	for(int level = 0; level < GameConstants::CREATURES_PER_TOWN; level++) | ||||
| 	for(int level = 0; level < developmentInfo.town->town->creatures.size(); level++) | ||||
| 	{ | ||||
| 		logAi->trace("Checking dwelling level %d", level); | ||||
| 		BuildingInfo nextToBuild = BuildingInfo(); | ||||
|  | ||||
| 		for(BuildingID prefix : prefixes) | ||||
| 		for(int upgradeIndex : {1, 0}) | ||||
| 		{ | ||||
| 			BuildingID building = BuildingID(prefix + level); | ||||
| 			BuildingID building = BuildingID(BuildingID::getDwellingFromLevel(level, upgradeIndex)); | ||||
|  | ||||
| 			if(!vstd::contains(buildings, building)) | ||||
| 				continue; // no such building in town | ||||
| @@ -211,8 +209,8 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite( | ||||
|  | ||||
| 	if(BuildingID::DWELL_FIRST <= toBuild && toBuild <= BuildingID::DWELL_UP_LAST) | ||||
| 	{ | ||||
| 		creatureLevel = (toBuild - BuildingID::DWELL_FIRST) % GameConstants::CREATURES_PER_TOWN; | ||||
| 		creatureUpgrade = (toBuild - BuildingID::DWELL_FIRST) / GameConstants::CREATURES_PER_TOWN; | ||||
| 		creatureLevel = BuildingID::getLevelFromDwelling(toBuild); | ||||
| 		creatureUpgrade = BuildingID::getUpgradedFromDwelling(toBuild); | ||||
| 	} | ||||
| 	else if(toBuild == BuildingID::HORDE_1 || toBuild == BuildingID::HORDE_1_UPGR) | ||||
| 	{ | ||||
|   | ||||
| @@ -143,9 +143,9 @@ static const std::vector<BuildingID> basicGoldSource = { BuildingID::TOWN_HALL, | ||||
| static const std::vector<BuildingID> defence = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE }; | ||||
| static const std::vector<BuildingID> capitolAndRequirements = { BuildingID::FORT, BuildingID::CITADEL, BuildingID::CASTLE, BuildingID::CAPITOL }; | ||||
| static const std::vector<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 }; | ||||
| BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7, BuildingID::DWELL_LVL_8 }; | ||||
| static const std::vector<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 }; | ||||
| BuildingID::DWELL_LVL_4_UP, BuildingID::DWELL_LVL_5_UP, BuildingID::DWELL_LVL_6_UP, BuildingID::DWELL_LVL_7_UP, BuildingID::DWELL_LVL_8_UP }; | ||||
| static const std::vector<BuildingID> unitGrowth = { BuildingID::HORDE_1, BuildingID::HORDE_1_UPGR, BuildingID::HORDE_2, BuildingID::HORDE_2_UPGR }; | ||||
| static const std::vector<BuildingID> _spells = { BuildingID::MAGES_GUILD_1, BuildingID::MAGES_GUILD_2, BuildingID::MAGES_GUILD_3, | ||||
| BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5 }; | ||||
|   | ||||
| @@ -109,7 +109,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() | ||||
| 			if(upgradeNumber < 0) | ||||
| 				continue; | ||||
|  | ||||
| 			BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * GameConstants::CREATURES_PER_TOWN); | ||||
| 			BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * t->town->creatures.size()); | ||||
| 			if(t->hasBuilt(bid) && ai->ah->freeResources().canAfford(creature->getFullRecruitCost())) //this assumes only creatures with dwellings are assigned to faction | ||||
| 			{ | ||||
| 				solutions.push_back(sptr(BuyArmy(t, creature->getAIValue() * this->value).setobjid(objid))); | ||||
|   | ||||
| @@ -163,7 +163,7 @@ void CBuildingRect::showPopupWindow(const Point & cursorPosition) | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		int level = ( bid - BuildingID::DWELL_FIRST ) % GameConstants::CREATURES_PER_TOWN; | ||||
| 		int level = BuildingID::getLevelFromDwelling(bid); | ||||
| 		GH.windows().createAndPushWindow<CDwellingInfoBox>(parent->pos.x+parent->pos.w / 2, parent->pos.y+parent->pos.h  /2, town, level); | ||||
| 	} | ||||
| } | ||||
| @@ -237,7 +237,7 @@ std::string CBuildingRect::getSubtitle()//hover text for building | ||||
| 		return town->town->buildings.at(getBuilding()->bid)->getNameTranslated(); | ||||
| 	else//dwellings - recruit %creature% | ||||
| 	{ | ||||
| 		auto & availableCreatures = town->creatures[(bid-30)%GameConstants::CREATURES_PER_TOWN].second; | ||||
| 		auto & availableCreatures = town->creatures[(bid-30)%town->town->creatures.size()].second; | ||||
| 		if(availableCreatures.size()) | ||||
| 		{ | ||||
| 			int creaID = availableCreatures.back();//taking last of available creatures | ||||
| @@ -688,7 +688,7 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil | ||||
|  | ||||
| 	if (building >= BuildingID::DWELL_FIRST) | ||||
| 	{ | ||||
| 		enterDwelling((building-BuildingID::DWELL_FIRST)%GameConstants::CREATURES_PER_TOWN); | ||||
| 		enterDwelling((BuildingID::getLevelFromDwelling(building))); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| @@ -800,10 +800,10 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil | ||||
| 						break; | ||||
|  | ||||
| 				case BuildingSubID::PORTAL_OF_SUMMONING: | ||||
| 						if (town->creatures[GameConstants::CREATURES_PER_TOWN].second.empty())//No creatures | ||||
| 						if (town->creatures[town->town->creatures.size()].second.empty())//No creatures | ||||
| 							LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30]); | ||||
| 						else | ||||
| 							enterDwelling(GameConstants::CREATURES_PER_TOWN); | ||||
| 							enterDwelling(town->town->creatures.size()); | ||||
| 						break; | ||||
|  | ||||
| 				case BuildingSubID::BALLISTA_YARD: | ||||
| @@ -921,8 +921,8 @@ void CCastleBuildings::enterDwelling(int level) | ||||
| void CCastleBuildings::enterToTheQuickRecruitmentWindow() | ||||
| { | ||||
| 	const auto beginIt = town->creatures.cbegin(); | ||||
| 	const auto afterLastIt = town->creatures.size() > GameConstants::CREATURES_PER_TOWN | ||||
| 		? std::next(beginIt, GameConstants::CREATURES_PER_TOWN) | ||||
| 	const auto afterLastIt = town->creatures.size() > town->town->creatures.size() | ||||
| 		? std::next(beginIt, town->town->creatures.size()) | ||||
| 		: town->creatures.cend(); | ||||
| 	const auto hasSomeoneToRecruit = std::any_of(beginIt, afterLastIt, | ||||
| 		[](const auto & creatureInfo) { return creatureInfo.first > 0; }); | ||||
| @@ -1759,7 +1759,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town): | ||||
| { | ||||
| 	OBJECT_CONSTRUCTION; | ||||
| 	ui32 fortSize = static_cast<ui32>(town->creatures.size()); | ||||
| 	if(fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty()) | ||||
| 	if(fortSize > town->town->creatures.size() && town->creatures.back().second.empty()) | ||||
| 		fortSize--; | ||||
|  | ||||
| 	const CBuilding * fortBuilding = town->town->buildings.at(BuildingID(town->fortLevel()+6)); | ||||
| @@ -1777,25 +1777,25 @@ CFortScreen::CFortScreen(const CGTownInstance * town): | ||||
|  | ||||
| 	if(fortSize == GameConstants::CREATURES_PER_TOWN) | ||||
| 	{ | ||||
| 		positions.push_back(Point(206,421)); | ||||
| 		positions.push_back(Point(10, 421)); | ||||
| 		positions.push_back(Point(404,421)); | ||||
| 	} | ||||
| 	else | ||||
| 	{ | ||||
| 		positions.push_back(Point(10, 421)); | ||||
| 		positions.push_back(Point(404,421)); | ||||
| 		positions.push_back(Point(206,421)); | ||||
| 	} | ||||
|  | ||||
| 	for(ui32 i=0; i<fortSize; i++) | ||||
| 	{ | ||||
| 		BuildingID buildingID; | ||||
| 		if(fortSize == GameConstants::CREATURES_PER_TOWN) | ||||
| 		if(fortSize == town->town->creatures.size()) | ||||
| 		{ | ||||
| 			BuildingID dwelling = BuildingID::DWELL_UP_FIRST+i; | ||||
| 			BuildingID dwelling = BuildingID::getDwellingFromLevel(i, 1); | ||||
|  | ||||
| 			if(vstd::contains(town->builtBuildings, dwelling)) | ||||
| 				buildingID = BuildingID(BuildingID::DWELL_UP_FIRST+i); | ||||
| 				buildingID = BuildingID(BuildingID::getDwellingFromLevel(i, 1)); | ||||
| 			else | ||||
| 				buildingID = BuildingID(BuildingID::DWELL_FIRST+i); | ||||
| 				buildingID = BuildingID(BuildingID::getDwellingFromLevel(i, 0)); | ||||
| 		} | ||||
| 		else | ||||
| 		{ | ||||
| @@ -1817,13 +1817,13 @@ CFortScreen::CFortScreen(const CGTownInstance * town): | ||||
| ImagePath CFortScreen::getBgName(const CGTownInstance * town) | ||||
| { | ||||
| 	ui32 fortSize = static_cast<ui32>(town->creatures.size()); | ||||
| 	if(fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty()) | ||||
| 	if(fortSize > town->town->creatures.size() && town->creatures.back().second.empty()) | ||||
| 		fortSize--; | ||||
|  | ||||
| 	if(fortSize == GameConstants::CREATURES_PER_TOWN) | ||||
| 		return ImagePath::builtin("TPCASTL7"); | ||||
| 	else | ||||
| 		return ImagePath::builtin("TPCASTL8"); | ||||
| 	else | ||||
| 		return ImagePath::builtin("TPCASTL7"); | ||||
| } | ||||
|  | ||||
| void CFortScreen::creaturesChangedEventHandler() | ||||
| @@ -1897,9 +1897,9 @@ const CCreature * CFortScreen::RecruitArea::getMyCreature() | ||||
|  | ||||
| const CBuilding * CFortScreen::RecruitArea::getMyBuilding() | ||||
| { | ||||
| 	BuildingID myID = BuildingID(BuildingID::DWELL_FIRST + level); | ||||
| 	BuildingID myID = BuildingID(BuildingID::getDwellingFromLevel(level, 0)); | ||||
|  | ||||
| 	if (level == GameConstants::CREATURES_PER_TOWN) | ||||
| 	if (level == town->town->creatures.size()) | ||||
| 		return town->town->getSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING); | ||||
|  | ||||
| 	if (!town->town->buildings.count(myID)) | ||||
| @@ -1910,7 +1910,7 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding() | ||||
| 	{ | ||||
| 		if (town->hasBuilt(myID)) | ||||
| 			build = town->town->buildings.at(myID); | ||||
| 		myID.advance(GameConstants::CREATURES_PER_TOWN); | ||||
| 		myID.advance(town->town->creatures.size()); | ||||
| 	} | ||||
| 	return build; | ||||
| } | ||||
|   | ||||
| @@ -51,7 +51,7 @@ void QuickRecruitmentWindow::setCreaturePurchaseCards() | ||||
| { | ||||
| 	int availableAmount = getAvailableCreatures(); | ||||
| 	Point position = Point((pos.w - 100*availableAmount - 8*(availableAmount-1))/2,64); | ||||
| 	for (int i = 0; i < GameConstants::CREATURES_PER_TOWN; i++) | ||||
| 	for (int i = 0; i < town->town->creatures.size(); i++) | ||||
| 	{ | ||||
| 		if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first) | ||||
| 		{ | ||||
| @@ -106,7 +106,16 @@ void QuickRecruitmentWindow::purchaseUnits() | ||||
| 	{ | ||||
| 		if(selected->slider->getValue()) | ||||
| 		{ | ||||
| 			auto onRecruit = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, selected->creatureOnTheCard->getLevel()-1); }; | ||||
| 			int level = 0; | ||||
| 			int i = 0; | ||||
| 			for(auto c : town->town->creatures) | ||||
| 			{ | ||||
| 				for(auto c2 : c) | ||||
| 					if(c2 == selected->creatureOnTheCard->getId()) | ||||
| 						level = i; | ||||
| 				i++; | ||||
| 			} | ||||
| 			auto onRecruit = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, level); }; | ||||
| 			CreatureID crid =  selected->creatureOnTheCard->getId(); | ||||
| 			SlotID dstslot = town -> getSlotFor(crid); | ||||
| 			if(!dstslot.validSlot()) | ||||
| @@ -120,7 +129,7 @@ void QuickRecruitmentWindow::purchaseUnits() | ||||
| int QuickRecruitmentWindow::getAvailableCreatures() | ||||
| { | ||||
| 	int creaturesAmount = 0; | ||||
| 	for (int i=0; i< GameConstants::CREATURES_PER_TOWN; i++) | ||||
| 	for (int i=0; i< town->town->creatures.size(); i++) | ||||
| 		if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first) | ||||
| 			creaturesAmount++; | ||||
| 	return creaturesAmount; | ||||
|   | ||||
| @@ -765,7 +765,7 @@ void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects) | ||||
| 		auto addBonusForTier = [&](int tier, std::shared_ptr<Bonus> b) { | ||||
| 			assert(vstd::iswithin(tier, 1, 7)); | ||||
| 			//bonuses from level 7 are given to high-level creatures too | ||||
| 			auto max = tier == GameConstants::CREATURES_PER_TOWN ? std::numeric_limits<int>::max() : tier + 1; | ||||
| 			auto max = tier == 7 ? std::numeric_limits<int>::max() : tier + 1; | ||||
| 			auto limiter = std::make_shared<CreatureLevelLimiter>(tier, max); | ||||
| 			b->addLimiter(limiter); | ||||
| 			globalEffects.addNewBonus(b); | ||||
|   | ||||
| @@ -280,6 +280,7 @@ public: | ||||
| 	enum Type | ||||
| 	{ | ||||
| 		DEFAULT = -50, | ||||
| 		HORDE_PLACEHOLDER8 = -37, | ||||
| 		HORDE_PLACEHOLDER7 = -36, | ||||
| 		HORDE_PLACEHOLDER6 = -35, | ||||
| 		HORDE_PLACEHOLDER5 = -34, | ||||
| @@ -297,7 +298,7 @@ public: | ||||
| 		HORDE_2_UPGR,   GRAIL,         EXTRA_TOWN_HALL,   EXTRA_CITY_HALL, EXTRA_CAPITOL, | ||||
| 		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_6_UP, DWELL_UP_LAST=43, DWELL_LVL_8=150, DWELL_LVL_8_UP=151, | ||||
|  | ||||
| 		DWELL_LVL_1 = DWELL_FIRST, | ||||
| 		DWELL_LVL_7 = DWELL_LAST, | ||||
| @@ -313,6 +314,44 @@ public: | ||||
|  | ||||
| 	}; | ||||
|  | ||||
| private: | ||||
| 	static std::vector<std::vector<Type>> getDwellings() | ||||
| 	{ | ||||
| 		std::vector<Type> dwellings = { DWELL_LVL_1, DWELL_LVL_2, DWELL_LVL_3, DWELL_LVL_4, DWELL_LVL_5, DWELL_LVL_6, DWELL_LVL_7, DWELL_LVL_8 }; | ||||
| 		std::vector<Type> dwellingsUp = { DWELL_LVL_1_UP, DWELL_LVL_2_UP, DWELL_LVL_3_UP, DWELL_LVL_4_UP, DWELL_LVL_5_UP, DWELL_LVL_6_UP, DWELL_LVL_7_UP, DWELL_LVL_8_UP }; | ||||
| 		return {dwellings, dwellingsUp}; | ||||
| 	} | ||||
|  | ||||
| public: | ||||
| 	static Type getDwellingFromLevel(int level, int upgradeIndex) | ||||
| 	{ | ||||
| 		return getDwellings()[upgradeIndex][level]; | ||||
| 	} | ||||
|  | ||||
| 	static int getLevelFromDwelling(BuildingIDBase dwelling) | ||||
| 	{ | ||||
| 		for(int i = 0; i < 2; i++) | ||||
| 		{ | ||||
| 			auto tmp = getDwellings()[i]; | ||||
| 			auto it = std::find(tmp.begin(), tmp.end(), dwelling); | ||||
| 			if (it != tmp.end()) | ||||
| 				return std::distance(tmp.begin(), it); | ||||
| 		} | ||||
| 		return (dwelling - DWELL_FIRST) % (GameConstants::CREATURES_PER_TOWN - 1); | ||||
| 	} | ||||
|  | ||||
| 	static int getUpgradedFromDwelling(BuildingIDBase dwelling) | ||||
| 	{ | ||||
| 		for(int i = 0; i < 2; i++) | ||||
| 		{ | ||||
| 			auto tmp = getDwellings()[i]; | ||||
| 			auto it = std::find(tmp.begin(), tmp.end(), dwelling); | ||||
| 			if (it != tmp.end()) | ||||
| 				return i; | ||||
| 		} | ||||
| 		return (dwelling - DWELL_FIRST) / (GameConstants::CREATURES_PER_TOWN - 1); | ||||
| 	} | ||||
|  | ||||
| 	bool IsSpecialOrGrail() const | ||||
| 	{ | ||||
| 		return num == SPECIAL_1 || num == SPECIAL_2 || num == SPECIAL_3 || num == SPECIAL_4 || num == GRAIL; | ||||
|   | ||||
| @@ -22,7 +22,7 @@ namespace GameConstants | ||||
|  | ||||
| 	constexpr int ALL_PLAYERS = 255; //bitfield | ||||
|  | ||||
| 	constexpr int CREATURES_PER_TOWN = 7; //without upgrades | ||||
| 	constexpr int CREATURES_PER_TOWN = 8; //without upgrades | ||||
| 	constexpr int SPELL_LEVELS = 5; | ||||
| 	constexpr int SPELL_SCHOOL_LEVELS = 4; | ||||
| 	constexpr int DEFAULT_SCHOOLS = 4; | ||||
|   | ||||
| @@ -56,7 +56,7 @@ namespace NSecondarySkill | ||||
|  | ||||
| namespace EBuildingType | ||||
| { | ||||
| 	const std::string names [44] = | ||||
| 	const std::string names [46] = | ||||
| 	{ | ||||
| 		"mageGuild1",       "mageGuild2",       "mageGuild3",       "mageGuild4",       "mageGuild5",       //  5 | ||||
| 		"tavern",           "shipyard",         "fort",             "citadel",          "castle",           // 10 | ||||
| @@ -66,7 +66,8 @@ namespace EBuildingType | ||||
| 		"horde2Upgr",       "grail",            "extraTownHall",    "extraCityHall",    "extraCapitol",     // 30 | ||||
| 		"dwellingLvl1",     "dwellingLvl2",     "dwellingLvl3",     "dwellingLvl4",     "dwellingLvl5",     // 35 | ||||
| 		"dwellingLvl6",     "dwellingLvl7",     "dwellingUpLvl1",   "dwellingUpLvl2",   "dwellingUpLvl3",   // 40 | ||||
| 		"dwellingUpLvl4",   "dwellingUpLvl5",   "dwellingUpLvl6",   "dwellingUpLvl7" | ||||
| 		"dwellingUpLvl4",   "dwellingUpLvl5",   "dwellingUpLvl6",   "dwellingUpLvl7",   "dwellingLvl8", | ||||
| 		"dwellingUpLvl8" | ||||
| 	}; | ||||
| } | ||||
|  | ||||
| @@ -163,6 +164,7 @@ namespace MappedKeys | ||||
| 		{ "dwellingLvl5", BuildingID::DWELL_LVL_5 }, | ||||
| 		{ "dwellingLvl6", BuildingID::DWELL_LVL_6 }, | ||||
| 		{ "dwellingLvl7", BuildingID::DWELL_LVL_7 }, | ||||
| 		{ "dwellingLvl8", BuildingID::DWELL_LVL_8 }, | ||||
| 		{ "dwellingUpLvl1", BuildingID::DWELL_LVL_1_UP }, | ||||
| 		{ "dwellingUpLvl2", BuildingID::DWELL_LVL_2_UP }, | ||||
| 		{ "dwellingUpLvl3", BuildingID::DWELL_LVL_3_UP }, | ||||
| @@ -170,6 +172,7 @@ namespace MappedKeys | ||||
| 		{ "dwellingUpLvl5", BuildingID::DWELL_LVL_5_UP }, | ||||
| 		{ "dwellingUpLvl6", BuildingID::DWELL_LVL_6_UP }, | ||||
| 		{ "dwellingUpLvl7", BuildingID::DWELL_LVL_7_UP }, | ||||
| 		{ "dwellingUpLvl8", BuildingID::DWELL_LVL_8_UP }, | ||||
| 	}; | ||||
|  | ||||
| 	static const std::map<std::string, BuildingSubID::EBuildingSubID> SPECIAL_BUILDINGS = | ||||
|   | ||||
| @@ -9,6 +9,9 @@ | ||||
|  */ | ||||
| #include "StdInc.h" | ||||
| #include "CBuildingHandler.h" | ||||
| #include "VCMI_Lib.h" | ||||
| #include "../faction/CTown.h" | ||||
| #include "../faction/CTownHandler.h" | ||||
|  | ||||
| VCMI_LIB_NAMESPACE_BEGIN | ||||
|  | ||||
| @@ -36,7 +39,7 @@ BuildingID CBuildingHandler::campToERMU(int camp, FactionID townType, const std: | ||||
| 	}; | ||||
|  | ||||
| 	int curPos = static_cast<int>(campToERMU.size()); | ||||
| 	for (int i=0; i<GameConstants::CREATURES_PER_TOWN; ++i) | ||||
| 	for (int i=0; i<(*VLC->townh)[townType]->town->creatures.size(); ++i) | ||||
| 	{ | ||||
| 		if(camp == curPos) //non-upgraded | ||||
| 			return BuildingID(30 + i); | ||||
| @@ -53,7 +56,7 @@ BuildingID CBuildingHandler::campToERMU(int camp, FactionID townType, const std: | ||||
| 				{ | ||||
| 					if (hordeLvlsPerTType[townType.getNum()][0] == i) | ||||
| 					{ | ||||
| 						BuildingID dwellingID(BuildingID::DWELL_UP_FIRST + hordeLvlsPerTType[townType.getNum()][0]); | ||||
| 						BuildingID dwellingID(BuildingID::getDwellingFromLevel(hordeLvlsPerTType[townType.getNum()][0], 1)); | ||||
|  | ||||
| 						if(vstd::contains(builtBuildings, dwellingID)) //if upgraded dwelling is built | ||||
| 							return BuildingID::HORDE_1_UPGR; | ||||
| @@ -64,7 +67,7 @@ BuildingID CBuildingHandler::campToERMU(int camp, FactionID townType, const std: | ||||
| 					{ | ||||
| 						if(hordeLvlsPerTType[townType.getNum()].size() > 1) | ||||
| 						{ | ||||
| 							BuildingID dwellingID(BuildingID::DWELL_UP_FIRST + hordeLvlsPerTType[townType.getNum()][1]); | ||||
| 							BuildingID dwellingID(BuildingID::getDwellingFromLevel(hordeLvlsPerTType[townType.getNum()][1], 1)); | ||||
|  | ||||
| 							if(vstd::contains(builtBuildings, dwellingID)) //if upgraded dwelling is built | ||||
| 								return BuildingID::HORDE_2_UPGR; | ||||
|   | ||||
| @@ -795,10 +795,11 @@ void CGameState::initTowns() | ||||
| 	for (auto & vti : map->towns) | ||||
| 	{ | ||||
| 		assert(vti->town); | ||||
| 		assert(vti->town->creatures.size() <= GameConstants::CREATURES_PER_TOWN);  | ||||
|  | ||||
| 		constexpr std::array basicDwellings = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7 }; | ||||
| 		constexpr std::array upgradedDwellings = { BuildingID::DWELL_UP_FIRST, 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 }; | ||||
| 		constexpr std::array hordes = { BuildingID::HORDE_PLACEHOLDER1, BuildingID::HORDE_PLACEHOLDER2, BuildingID::HORDE_PLACEHOLDER3, BuildingID::HORDE_PLACEHOLDER4, BuildingID::HORDE_PLACEHOLDER5, BuildingID::HORDE_PLACEHOLDER6, BuildingID::HORDE_PLACEHOLDER7 }; | ||||
| 		constexpr std::array basicDwellings = { BuildingID::DWELL_FIRST, BuildingID::DWELL_LVL_2, BuildingID::DWELL_LVL_3, BuildingID::DWELL_LVL_4, BuildingID::DWELL_LVL_5, BuildingID::DWELL_LVL_6, BuildingID::DWELL_LVL_7, BuildingID::DWELL_LVL_8 }; | ||||
| 		constexpr std::array upgradedDwellings = { BuildingID::DWELL_UP_FIRST, 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, BuildingID::DWELL_LVL_8_UP }; | ||||
| 		constexpr std::array hordes = { BuildingID::HORDE_PLACEHOLDER1, BuildingID::HORDE_PLACEHOLDER2, BuildingID::HORDE_PLACEHOLDER3, BuildingID::HORDE_PLACEHOLDER4, BuildingID::HORDE_PLACEHOLDER5, BuildingID::HORDE_PLACEHOLDER6, BuildingID::HORDE_PLACEHOLDER7, BuildingID::HORDE_PLACEHOLDER8 }; | ||||
|  | ||||
| 		//init buildings | ||||
| 		if(vstd::contains(vti->builtBuildings, BuildingID::DEFAULT)) //give standard set of buildings | ||||
| @@ -823,7 +824,7 @@ void CGameState::initTowns() | ||||
| 		vti->builtBuildings.insert(BuildingID::VILLAGE_HALL); | ||||
|  | ||||
| 		//init hordes | ||||
| 		for (int i = 0; i < GameConstants::CREATURES_PER_TOWN; i++) | ||||
| 		for (int i = 0; i < vti->town->creatures.size(); i++) | ||||
| 		{ | ||||
| 			if (vstd::contains(vti->builtBuildings, hordes[i])) //if we have horde for this level | ||||
| 			{ | ||||
| @@ -863,7 +864,7 @@ void CGameState::initTowns() | ||||
| 		//town events | ||||
| 		for(CCastleEvent &ev : vti->events) | ||||
| 		{ | ||||
| 			for (int i = 0; i<GameConstants::CREATURES_PER_TOWN; i++) | ||||
| 			for (int i = 0; i<vti->getTown()->creatures.size(); i++) | ||||
| 				if (vstd::contains(ev.buildings,hordes[i])) //if we have horde for this level | ||||
| 				{ | ||||
| 					ev.buildings.erase(hordes[i]); | ||||
|   | ||||
| @@ -128,7 +128,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const | ||||
| { | ||||
| 	GrowthInfo ret; | ||||
|  | ||||
| 	if (level<0 || level >=GameConstants::CREATURES_PER_TOWN) | ||||
| 	if (level<0 || level >=town->creatures.size()) | ||||
| 		return ret; | ||||
| 	if (creatures[level].second.empty()) | ||||
| 		return ret; //no dwelling | ||||
| @@ -514,16 +514,16 @@ void CGTownInstance::initObj(vstd::RNG & rand) ///initialize town structures | ||||
| 	blockVisit = true; | ||||
|  | ||||
| 	if(townEnvisagesBuilding(BuildingSubID::PORTAL_OF_SUMMONING)) //Dungeon for example | ||||
| 		creatures.resize(GameConstants::CREATURES_PER_TOWN + 1); | ||||
| 		creatures.resize(town->creatures.size() + 1); | ||||
| 	else | ||||
| 		creatures.resize(GameConstants::CREATURES_PER_TOWN); | ||||
| 		creatures.resize(town->creatures.size()); | ||||
|  | ||||
| 	for (int level = 0; level < GameConstants::CREATURES_PER_TOWN; level++) | ||||
| 	for (int level = 0; level < town->creatures.size(); level++) | ||||
| 	{ | ||||
| 		BuildingID buildID = BuildingID(BuildingID::DWELL_FIRST + level); | ||||
| 		BuildingID buildID = BuildingID(BuildingID::getDwellingFromLevel(level, 0)); | ||||
| 		int upgradeNum = 0; | ||||
|  | ||||
| 		for (; town->buildings.count(buildID); upgradeNum++, buildID.advance(GameConstants::CREATURES_PER_TOWN)) | ||||
| 		for (; town->buildings.count(buildID); upgradeNum++, buildID.advance(town->creatures.size())) | ||||
| 		{ | ||||
| 			if (hasBuilt(buildID) && town->creatures.at(level).size() > upgradeNum) | ||||
| 				creatures[level].second.push_back(town->creatures[level][upgradeNum]); | ||||
| @@ -591,7 +591,7 @@ void CGTownInstance::newTurn(vstd::RNG & rand) const | ||||
| 			} | ||||
| 			if ((stacksCount() < GameConstants::ARMY_SIZE && rand.nextInt(99) < 25) || Slots().empty()) //add new stack | ||||
| 			{ | ||||
| 				int i = rand.nextInt(std::min(GameConstants::CREATURES_PER_TOWN, cb->getDate(Date::MONTH) << 1) - 1); | ||||
| 				int i = rand.nextInt(std::min((int)town->creatures.size(), cb->getDate(Date::MONTH) << 1) - 1); | ||||
| 				if (!town->creatures[i].empty()) | ||||
| 				{ | ||||
| 					CreatureID c = town->creatures[i][0]; | ||||
|   | ||||
| @@ -57,6 +57,7 @@ std::string defaultBuildingIdConversion(BuildingID bId) | ||||
| 		case BuildingID::DWELL_LVL_5: return "DWELL_LVL_5"; | ||||
| 		case BuildingID::DWELL_LVL_6: return "DWELL_LVL_6"; | ||||
| 		case BuildingID::DWELL_LVL_7: return "DWELL_LVL_7"; | ||||
| 		case BuildingID::DWELL_LVL_8: return "DWELL_LVL_8"; | ||||
| 		case BuildingID::DWELL_LVL_1_UP: return "DWELL_LVL_1_UP"; | ||||
| 		case BuildingID::DWELL_LVL_2_UP: return "DWELL_LVL_2_UP"; | ||||
| 		case BuildingID::DWELL_LVL_3_UP: return "DWELL_LVL_3_UP"; | ||||
| @@ -64,6 +65,7 @@ std::string defaultBuildingIdConversion(BuildingID bId) | ||||
| 		case BuildingID::DWELL_LVL_5_UP: return "DWELL_LVL_5_UP"; | ||||
| 		case BuildingID::DWELL_LVL_6_UP: return "DWELL_LVL_6_UP"; | ||||
| 		case BuildingID::DWELL_LVL_7_UP: return "DWELL_LVL_7_UP"; | ||||
| 		case BuildingID::DWELL_LVL_8_UP: return "DWELL_LVL_8_UP"; | ||||
| 		default: | ||||
| 			return "UNKNOWN"; | ||||
| 	} | ||||
|   | ||||
| @@ -599,12 +599,12 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa | ||||
| 		return; | ||||
| 	} | ||||
|  | ||||
| 	if (forced || town->creatures.at(GameConstants::CREATURES_PER_TOWN).second.empty())//we need to change creature | ||||
| 	if (forced || town->creatures.at(town->town->creatures.size()).second.empty())//we need to change creature | ||||
| 		{ | ||||
| 			SetAvailableCreatures ssi; | ||||
| 			ssi.tid = town->id; | ||||
| 			ssi.creatures = town->creatures; | ||||
| 			ssi.creatures[GameConstants::CREATURES_PER_TOWN].second.clear();//remove old one | ||||
| 			ssi.creatures[town->town->creatures.size()].second.clear();//remove old one | ||||
|  | ||||
| 			const std::vector<ConstTransitivePtr<CGDwelling> > &dwellings = p->dwellings; | ||||
| 			if (dwellings.empty())//no dwellings - just remove | ||||
| @@ -620,13 +620,13 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa | ||||
|  | ||||
| 			if (clear) | ||||
| 			{ | ||||
| 				ssi.creatures[GameConstants::CREATURES_PER_TOWN].first = std::max(1, (VLC->creh->objects.at(creatureId)->getGrowth())/2); | ||||
| 				ssi.creatures[town->town->creatures.size()].first = std::max(1, (VLC->creh->objects.at(creatureId)->getGrowth())/2); | ||||
| 			} | ||||
| 			else | ||||
| 			{ | ||||
| 				ssi.creatures[GameConstants::CREATURES_PER_TOWN].first = VLC->creh->objects.at(creatureId)->getGrowth(); | ||||
| 				ssi.creatures[town->town->creatures.size()].first = VLC->creh->objects.at(creatureId)->getGrowth(); | ||||
| 			} | ||||
| 			ssi.creatures[GameConstants::CREATURES_PER_TOWN].second.push_back(creatureId); | ||||
| 			ssi.creatures[town->town->creatures.size()].second.push_back(creatureId); | ||||
| 			sendAndApply(&ssi); | ||||
| 		} | ||||
| } | ||||
| @@ -877,7 +877,7 @@ void CGameHandler::onNewTurn() | ||||
| 			} | ||||
| 			auto & sac = n.cres.at(t->id); | ||||
|  | ||||
| 			for (int k=0; k < GameConstants::CREATURES_PER_TOWN; k++) //creature growths | ||||
| 			for (int k=0; k < t->town->creatures.size(); k++) //creature growths | ||||
| 			{ | ||||
| 				if (!t->creatures.at(k).second.empty()) // there are creatures at this level | ||||
| 				{ | ||||
| @@ -2378,8 +2378,8 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, | ||||
| 	{ | ||||
| 		if(buildingID >= BuildingID::DWELL_FIRST) //dwelling | ||||
| 		{ | ||||
| 			int level = (buildingID - BuildingID::DWELL_FIRST) % GameConstants::CREATURES_PER_TOWN; | ||||
| 			int upgradeNumber = (buildingID - BuildingID::DWELL_FIRST) / GameConstants::CREATURES_PER_TOWN; | ||||
| 			int level = BuildingID::getLevelFromDwelling(buildingID); | ||||
| 			int upgradeNumber = BuildingID::getUpgradedFromDwelling(buildingID); | ||||
|  | ||||
| 			if(upgradeNumber >= t->town->creatures.at(level).size()) | ||||
| 			{ | ||||
|   | ||||
		Reference in New Issue
	
	Block a user