diff --git a/AI/VCAI/BuildingManager.cpp b/AI/VCAI/BuildingManager.cpp index 60d971086..6636e01ef 100644 --- a/AI/VCAI/BuildingManager.cpp +++ b/AI/VCAI/BuildingManager.cpp @@ -222,7 +222,7 @@ bool BuildingManager::getBuildingOptions(const CGTownInstance * t) std::vector extraBuildings; for (auto buildingInfo : t->getTown()->buildings) { - if (buildingInfo.first > BuildingID::DWELL_UP2_FIRST) + if (buildingInfo.first.IsDwelling() && BuildingID::getUpgradedFromDwelling(buildingInfo.first) > 1) extraBuildings.push_back(buildingInfo.first); } return tryBuildAnyStructure(t, extraBuildings); diff --git a/AI/VCAI/Goals/GatherTroops.cpp b/AI/VCAI/Goals/GatherTroops.cpp index 50b8fdce5..47c4a0151 100644 --- a/AI/VCAI/Goals/GatherTroops.cpp +++ b/AI/VCAI/Goals/GatherTroops.cpp @@ -109,7 +109,8 @@ TGoalVec GatherTroops::getAllPossibleSubgoals() if(upgradeNumber < 0) continue; - BuildingID bid(BuildingID::DWELL_FIRST + creature->getLevel() - 1 + upgradeNumber * t->getTown()->creatures.size()); + BuildingID bid(BuildingID::getDwellingFromLevel(creature->getLevel(), upgradeNumber)); + 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))); diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 3d917712e..2ab065ad0 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -157,7 +157,7 @@ void CBuildingRect::showPopupWindow(const Point & cursorPosition) BuildingID bid = getBuilding()->bid; const CBuilding *bld = town->getTown()->buildings.at(bid); - if (bid < BuildingID::DWELL_FIRST) + if (!bid.IsDwelling()) { CRClickPopup::createAndPush(CInfoWindow::genText(bld->getNameTranslated(), bld->getDescriptionTranslated()), std::make_shared(ComponentType::BUILDING, BuildingTypeUniqueID(bld->town->faction->getId(), bld->bid))); @@ -751,7 +751,7 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu return true; } - if (buildingToTest >= BuildingID::DWELL_FIRST) + if (buildingToTest.IsDwelling()) { enterDwelling((BuildingID::getLevelFromDwelling(buildingToTest))); return true; @@ -815,7 +815,7 @@ bool CCastleBuildings::buildingTryActivateCustomUI(BuildingID buildingToTest, Bu case BuildingSubID::CASTLE_GATE: if (LOCPLINT->makingTurn) { - enterCastleGate(); + enterCastleGate(buildingToTest); return true; } return false; @@ -902,7 +902,7 @@ void CCastleBuildings::enterBuilding(BuildingID building) LOCPLINT->showInfoDialog( town->getTown()->buildings.find(building)->second->getDescriptionTranslated(), comps); } -void CCastleBuildings::enterCastleGate() +void CCastleBuildings::enterCastleGate(BuildingID building) { if (!town->visitingHero) { @@ -929,7 +929,7 @@ void CCastleBuildings::enterCastleGate() } } - auto gateIcon = std::make_shared(town->getTown()->clientInfo.buildingsIcons, BuildingID::CASTLE_GATE);//will be deleted by selection window + auto gateIcon = std::make_shared(town->getTown()->clientInfo.buildingsIcons, building);//will be deleted by selection window auto wnd = std::make_shared(availableTowns, gateIcon, CGI->generaltexth->jktexts[40], CGI->generaltexth->jktexts[41], std::bind (&CCastleInterface::castleTeleport, LOCPLINT->castleInt, _1), 0, images); wnd->onPopup = [availableTowns](int index) { CRClickPopup::createAndPush(LOCPLINT->cb->getObjInstance(ObjectInstanceID(availableTowns[index])), GH.getCursorPosition()); }; diff --git a/client/windows/CCastleInterface.h b/client/windows/CCastleInterface.h index 717c1a748..855c62a1e 100644 --- a/client/windows/CCastleInterface.h +++ b/client/windows/CCastleInterface.h @@ -152,7 +152,7 @@ class CCastleBuildings : public CIntObject void enterBlacksmith(BuildingID building, ArtifactID artifactID);//support for blacksmith + ballista yard void enterBuilding(BuildingID building);//for buildings with simple description + pic left-click messages - void enterCastleGate(); + void enterCastleGate(BuildingID building); void enterFountain(const BuildingID & building, BuildingSubID::EBuildingSubID subID, BuildingID upgrades);//Rampart's fountains void openMagesGuild(); diff --git a/lib/constants/EntityIdentifiers.h b/lib/constants/EntityIdentifiers.h index 1aacfe828..72c896d47 100644 --- a/lib/constants/EntityIdentifiers.h +++ b/lib/constants/EntityIdentifiers.h @@ -289,38 +289,37 @@ public: HORDE_PLACEHOLDER1 = -30, NONE = -1, FIRST_REGULAR_ID = 0, - MAGES_GUILD_1 = 0, MAGES_GUILD_2, MAGES_GUILD_3, MAGES_GUILD_4, MAGES_GUILD_5, - TAVERN, SHIPYARD, FORT, CITADEL, CASTLE, - VILLAGE_HALL, TOWN_HALL, CITY_HALL, CAPITOL, MARKETPLACE, - 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_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_8=150, DWELL_LVL_8_UP=151, //150-154 reserved for 8. creature with potential upgrades + MAGES_GUILD_1 = 0, MAGES_GUILD_2, MAGES_GUILD_3, MAGES_GUILD_4, MAGES_GUILD_5, + TAVERN, SHIPYARD, FORT, CITADEL, CASTLE, + VILLAGE_HALL, TOWN_HALL, CITY_HALL, CAPITOL, MARKETPLACE, + 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_LVL_1 = DWELL_FIRST, - DWELL_LVL_7 = DWELL_LAST, - DWELL_LVL_1_UP = DWELL_UP_FIRST, - DWELL_LVL_7_UP = DWELL_UP_LAST, - - DWELL_UP2_FIRST = DWELL_LVL_7_UP + 1, - DWELL_LVL_1_UP2 = DWELL_UP2_FIRST, DWELL_LVL_2_UP2, DWELL_LVL_3_UP2, DWELL_LVL_4_UP2, DWELL_LVL_5_UP2, DWELL_LVL_6_UP2, DWELL_LVL_7_UP2, DWELL_LVL_8_UP2, - -// //Special buildings for towns. - CASTLE_GATE = SPECIAL_3, //Inferno - FREELANCERS_GUILD = SPECIAL_2, //Stronghold - ARTIFACT_MERCHANT = SPECIAL_1, + DWELL_LVL_1=30, DWELL_LVL_2, DWELL_LVL_3, DWELL_LVL_4, DWELL_LVL_5, DWELL_LVL_6, DWELL_LVL_7=36, + DWELL_LVL_1_UP=37, DWELL_LVL_2_UP, DWELL_LVL_3_UP, DWELL_LVL_4_UP, DWELL_LVL_5_UP, DWELL_LVL_6_UP, DWELL_LVL_7_UP=43, + DWELL_LVL_1_UP2, DWELL_LVL_2_UP2, DWELL_LVL_3_UP2, DWELL_LVL_4_UP2, DWELL_LVL_5_UP2, DWELL_LVL_6_UP2, DWELL_LVL_7_UP2, + DWELL_LVL_1_UP3, DWELL_LVL_2_UP3, DWELL_LVL_3_UP3, DWELL_LVL_4_UP3, DWELL_LVL_5_UP3, DWELL_LVL_6_UP3, DWELL_LVL_7_UP3, + DWELL_LVL_1_UP4, DWELL_LVL_2_UP4, DWELL_LVL_3_UP4, DWELL_LVL_4_UP4, DWELL_LVL_5_UP4, DWELL_LVL_6_UP4, DWELL_LVL_7_UP4, + DWELL_LVL_1_UP5, DWELL_LVL_2_UP5, DWELL_LVL_3_UP5, DWELL_LVL_4_UP5, DWELL_LVL_5_UP5, DWELL_LVL_6_UP5, DWELL_LVL_7_UP5, + //150-155 reserved for 8. creature with potential upgrades + DWELL_LVL_8=150, DWELL_LVL_8_UP=151, DWELL_LVL_8_UP2 = 152, DWELL_LVL_8_UP3 = 153, DWELL_LVL_8_UP4 = 154, DWELL_LVL_8_UP5 = 155, }; private: - static std::vector> getDwellings() + static std::array, 6> getDwellings() { - std::vector 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 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 }; - std::vector dwellingsUp2 = { DWELL_UP2_FIRST, DWELL_LVL_2_UP2, DWELL_LVL_3_UP2, DWELL_LVL_4_UP2, DWELL_LVL_5_UP2 , DWELL_LVL_6_UP2 , DWELL_LVL_7_UP2, DWELL_LVL_8_UP2 }; - return {dwellings, dwellingsUp, dwellingsUp2 }; + static const std::array, 6> allDwellings = {{ + { DWELL_LVL_1, DWELL_LVL_2, DWELL_LVL_3, DWELL_LVL_4, DWELL_LVL_5, DWELL_LVL_6, DWELL_LVL_7, DWELL_LVL_8 }, + { 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 }, + { DWELL_LVL_1_UP2, DWELL_LVL_2_UP2, DWELL_LVL_3_UP2, DWELL_LVL_4_UP2, DWELL_LVL_5_UP2, DWELL_LVL_6_UP2, DWELL_LVL_7_UP2, DWELL_LVL_8_UP2 }, + { DWELL_LVL_1_UP3, DWELL_LVL_2_UP3, DWELL_LVL_3_UP3, DWELL_LVL_4_UP3, DWELL_LVL_5_UP3, DWELL_LVL_6_UP3, DWELL_LVL_7_UP3, DWELL_LVL_8_UP3 }, + { DWELL_LVL_1_UP4, DWELL_LVL_2_UP4, DWELL_LVL_3_UP4, DWELL_LVL_4_UP4, DWELL_LVL_5_UP4, DWELL_LVL_6_UP4, DWELL_LVL_7_UP4, DWELL_LVL_8_UP4 }, + { DWELL_LVL_1_UP5, DWELL_LVL_2_UP5, DWELL_LVL_3_UP5, DWELL_LVL_4_UP5, DWELL_LVL_5_UP5, DWELL_LVL_6_UP5, DWELL_LVL_7_UP5, DWELL_LVL_8_UP5 } + }}; + + return allDwellings; } public: @@ -331,54 +330,45 @@ public: static int getLevelFromDwelling(BuildingIDBase dwelling) { - for(int i = 0; i < 2; i++) + for (const auto level : getDwellings()) { - auto tmp = getDwellings()[i]; - auto it = std::find(tmp.begin(), tmp.end(), dwelling); - if (it != tmp.end()) - return std::distance(tmp.begin(), it); + auto it = std::find(level.begin(), level.end(), dwelling); + if (it != level.end()) + return std::distance(level.begin(), it); } - if(dwelling >= BuildingIDBase::DWELL_LVL_8 && dwelling < BuildingIDBase::DWELL_LVL_8 + 5) - return 7; - else if (dwelling >= BuildingIDBase::DWELL_UP2_FIRST) - return (dwelling - DWELL_UP2_FIRST) % (GameConstants::CREATURES_PER_TOWN - 1); - else - return (dwelling - DWELL_FIRST) % (GameConstants::CREATURES_PER_TOWN - 1); + + throw std::runtime_error("Call to getLevelFromDwelling with building '" + std::to_string(dwelling.num) +"' that is not dwelling!"); } static int getUpgradedFromDwelling(BuildingIDBase dwelling) { - for(int i = 0; i < 2; i++) + const auto & dwellings = getDwellings(); + + for(int i = 0; i < dwellings.size(); i++) { - auto tmp = getDwellings()[i]; - auto it = std::find(tmp.begin(), tmp.end(), dwelling); - if (it != tmp.end()) + if (vstd::contains(dwellings[i], dwelling)) return i; } - if(dwelling >= BuildingIDBase::DWELL_LVL_8 && dwelling < BuildingIDBase::DWELL_LVL_8 + 5) - return dwelling - BuildingIDBase::DWELL_LVL_8; - else if (dwelling >= BuildingIDBase::DWELL_UP2_FIRST) - return (dwelling - DWELL_UP2_FIRST) / (GameConstants::CREATURES_PER_TOWN - 1); - else - return (dwelling - DWELL_FIRST) / (GameConstants::CREATURES_PER_TOWN - 1); + + throw std::runtime_error("Call to getUpgradedFromDwelling with building '" + std::to_string(dwelling.num) +"' that is not dwelling!"); } static void advanceDwelling(BuildingIDBase & dwelling) { - if(dwelling >= BuildingIDBase::DWELL_LVL_8 && dwelling < BuildingIDBase::DWELL_LVL_8 + 5) - dwelling.advance(1); - else - dwelling.advance(GameConstants::CREATURES_PER_TOWN - 1); + int level = getLevelFromDwelling(dwelling); + int upgrade = getUpgradedFromDwelling(dwelling); + + dwelling.setNum(getDwellingFromLevel(level, upgrade + 1)); } bool IsDwelling() const { - return (DWELL_FIRST <= num && num <= DWELL_UP_LAST) || (DWELL_LVL_8 <= num && num <= DWELL_LVL_8_UP) || (num >= DWELL_UP2_FIRST && num < DWELL_LVL_8); - } - - bool IsSpecialOrGrail() const - { - return num == SPECIAL_1 || num == SPECIAL_2 || num == SPECIAL_3 || num == SPECIAL_4 || num == GRAIL; + for (const auto level : getDwellings()) + { + if (vstd::contains(level, num)) + return true; + } + return false; } }; diff --git a/lib/gameState/CGameState.cpp b/lib/gameState/CGameState.cpp index dfaa0f738..fe7e3264d 100644 --- a/lib/gameState/CGameState.cpp +++ b/lib/gameState/CGameState.cpp @@ -803,8 +803,8 @@ void CGameState::initTowns() assert(vti->getTown()); assert(vti->getTown()->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, 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 basicDwellings = { 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_8 }; + constexpr std::array upgradedDwellings = { 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_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 diff --git a/lib/pathfinder/CPathfinder.cpp b/lib/pathfinder/CPathfinder.cpp index 35219cac2..deeb3fa5c 100644 --- a/lib/pathfinder/CPathfinder.cpp +++ b/lib/pathfinder/CPathfinder.cpp @@ -267,7 +267,7 @@ TeleporterTilesVector CPathfinderHelper::getCastleGates(const PathNodeInfo & sou for(const auto & town : getPlayerState(hero->tempOwner)->getTowns()) { if(town->id != source.nodeObject->id && town->visitingHero == nullptr - && town->hasBuilt(BuildingID::CASTLE_GATE, ETownType::INFERNO)) + && town->hasBuilt(BuildingSubID::CASTLE_GATE)) { allowedExits.push_back(town->visitablePos()); } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 0d8791791..07c8f50db 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2083,7 +2083,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID, //Performs stuff that has to be done before new building is built auto processBeforeBuiltStructure = [t, this](const BuildingID buildingID) { - if(buildingID >= BuildingID::DWELL_FIRST) //dwelling + if(buildingID.IsDwelling()) { int level = BuildingID::getLevelFromDwelling(buildingID); int upgradeNumber = BuildingID::getUpgradedFromDwelling(buildingID);