1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-24 22:14:36 +02:00

Merge pull request #4402 from Laserlicht/8th_creature

support for 8th creature (Factory)
This commit is contained in:
Ivan Savenko 2024-08-14 17:04:32 +03:00 committed by GitHub
commit 38311244a4
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
14 changed files with 117 additions and 62 deletions

View File

@ -31,16 +31,14 @@ void BuildAnalyzer::updateTownDwellings(TownDevelopmentInfo & developmentInfo)
} }
} }
BuildingID prefixes[] = {BuildingID::DWELL_UP_FIRST, BuildingID::DWELL_FIRST}; for(int level = 0; level < developmentInfo.town->town->creatures.size(); level++)
for(int level = 0; level < GameConstants::CREATURES_PER_TOWN; level++)
{ {
logAi->trace("Checking dwelling level %d", level); logAi->trace("Checking dwelling level %d", level);
BuildingInfo nextToBuild = BuildingInfo(); 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)) if(!vstd::contains(buildings, building))
continue; // no such building in town continue; // no such building in town
@ -211,8 +209,8 @@ BuildingInfo BuildAnalyzer::getBuildingOrPrerequisite(
if(BuildingID::DWELL_FIRST <= toBuild && toBuild <= BuildingID::DWELL_UP_LAST) if(BuildingID::DWELL_FIRST <= toBuild && toBuild <= BuildingID::DWELL_UP_LAST)
{ {
creatureLevel = (toBuild - BuildingID::DWELL_FIRST) % GameConstants::CREATURES_PER_TOWN; creatureLevel = BuildingID::getLevelFromDwelling(toBuild);
creatureUpgrade = (toBuild - BuildingID::DWELL_FIRST) / GameConstants::CREATURES_PER_TOWN; creatureUpgrade = BuildingID::getUpgradedFromDwelling(toBuild);
} }
else if(toBuild == BuildingID::HORDE_1 || toBuild == BuildingID::HORDE_1_UPGR) else if(toBuild == BuildingID::HORDE_1 || toBuild == BuildingID::HORDE_1_UPGR)
{ {

View File

@ -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> 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> 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, 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, 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> 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, 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 }; BuildingID::MAGES_GUILD_4, BuildingID::MAGES_GUILD_5 };

View File

@ -109,7 +109,7 @@ TGoalVec GatherTroops::getAllPossibleSubgoals()
if(upgradeNumber < 0) if(upgradeNumber < 0)
continue; 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 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))); solutions.push_back(sptr(BuyArmy(t, creature->getAIValue() * this->value).setobjid(objid)));

View File

@ -163,7 +163,7 @@ void CBuildingRect::showPopupWindow(const Point & cursorPosition)
} }
else 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); 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(); return town->town->buildings.at(getBuilding()->bid)->getNameTranslated();
else//dwellings - recruit %creature% 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()) if(availableCreatures.size())
{ {
int creaID = availableCreatures.back();//taking last of available creatures 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) if (building >= BuildingID::DWELL_FIRST)
{ {
enterDwelling((building-BuildingID::DWELL_FIRST)%GameConstants::CREATURES_PER_TOWN); enterDwelling((BuildingID::getLevelFromDwelling(building)));
} }
else else
{ {
@ -800,10 +800,10 @@ void CCastleBuildings::buildingClicked(BuildingID building, BuildingSubID::EBuil
break; break;
case BuildingSubID::PORTAL_OF_SUMMONING: 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]); LOCPLINT->showInfoDialog(CGI->generaltexth->tcommands[30]);
else else
enterDwelling(GameConstants::CREATURES_PER_TOWN); enterDwelling(town->town->creatures.size());
break; break;
case BuildingSubID::BALLISTA_YARD: case BuildingSubID::BALLISTA_YARD:
@ -921,8 +921,8 @@ void CCastleBuildings::enterDwelling(int level)
void CCastleBuildings::enterToTheQuickRecruitmentWindow() void CCastleBuildings::enterToTheQuickRecruitmentWindow()
{ {
const auto beginIt = town->creatures.cbegin(); const auto beginIt = town->creatures.cbegin();
const auto afterLastIt = town->creatures.size() > GameConstants::CREATURES_PER_TOWN const auto afterLastIt = town->creatures.size() > town->town->creatures.size()
? std::next(beginIt, GameConstants::CREATURES_PER_TOWN) ? std::next(beginIt, town->town->creatures.size())
: town->creatures.cend(); : town->creatures.cend();
const auto hasSomeoneToRecruit = std::any_of(beginIt, afterLastIt, const auto hasSomeoneToRecruit = std::any_of(beginIt, afterLastIt,
[](const auto & creatureInfo) { return creatureInfo.first > 0; }); [](const auto & creatureInfo) { return creatureInfo.first > 0; });
@ -1759,7 +1759,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
{ {
OBJECT_CONSTRUCTION; OBJECT_CONSTRUCTION;
ui32 fortSize = static_cast<ui32>(town->creatures.size()); 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--; fortSize--;
const CBuilding * fortBuilding = town->town->buildings.at(BuildingID(town->fortLevel()+6)); 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) 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 else
{ {
positions.push_back(Point(10, 421)); positions.push_back(Point(206,421));
positions.push_back(Point(404,421));
} }
for(ui32 i=0; i<fortSize; i++) for(ui32 i=0; i<fortSize; i++)
{ {
BuildingID buildingID; 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)) if(vstd::contains(town->builtBuildings, dwelling))
buildingID = BuildingID(BuildingID::DWELL_UP_FIRST+i); buildingID = BuildingID(BuildingID::getDwellingFromLevel(i, 1));
else else
buildingID = BuildingID(BuildingID::DWELL_FIRST+i); buildingID = BuildingID(BuildingID::getDwellingFromLevel(i, 0));
} }
else else
{ {
@ -1817,13 +1817,13 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
ImagePath CFortScreen::getBgName(const CGTownInstance * town) ImagePath CFortScreen::getBgName(const CGTownInstance * town)
{ {
ui32 fortSize = static_cast<ui32>(town->creatures.size()); 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--; fortSize--;
if(fortSize == GameConstants::CREATURES_PER_TOWN) if(fortSize == GameConstants::CREATURES_PER_TOWN)
return ImagePath::builtin("TPCASTL7");
else
return ImagePath::builtin("TPCASTL8"); return ImagePath::builtin("TPCASTL8");
else
return ImagePath::builtin("TPCASTL7");
} }
void CFortScreen::creaturesChangedEventHandler() void CFortScreen::creaturesChangedEventHandler()
@ -1897,9 +1897,9 @@ const CCreature * CFortScreen::RecruitArea::getMyCreature()
const CBuilding * CFortScreen::RecruitArea::getMyBuilding() 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); return town->town->getSpecialBuilding(BuildingSubID::PORTAL_OF_SUMMONING);
if (!town->town->buildings.count(myID)) if (!town->town->buildings.count(myID))
@ -1910,7 +1910,7 @@ const CBuilding * CFortScreen::RecruitArea::getMyBuilding()
{ {
if (town->hasBuilt(myID)) if (town->hasBuilt(myID))
build = town->town->buildings.at(myID); build = town->town->buildings.at(myID);
myID.advance(GameConstants::CREATURES_PER_TOWN); myID.advance(town->town->creatures.size());
} }
return build; return build;
} }

View File

@ -51,7 +51,7 @@ void QuickRecruitmentWindow::setCreaturePurchaseCards()
{ {
int availableAmount = getAvailableCreatures(); int availableAmount = getAvailableCreatures();
Point position = Point((pos.w - 100*availableAmount - 8*(availableAmount-1))/2,64); 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) 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()) 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(); CreatureID crid = selected->creatureOnTheCard->getId();
SlotID dstslot = town -> getSlotFor(crid); SlotID dstslot = town -> getSlotFor(crid);
if(!dstslot.validSlot()) if(!dstslot.validSlot())
@ -120,7 +129,7 @@ void QuickRecruitmentWindow::purchaseUnits()
int QuickRecruitmentWindow::getAvailableCreatures() int QuickRecruitmentWindow::getAvailableCreatures()
{ {
int creaturesAmount = 0; 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) if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first)
creaturesAmount++; creaturesAmount++;
return creaturesAmount; return creaturesAmount;

View File

@ -765,7 +765,7 @@ void CCreatureHandler::loadCrExpBon(CBonusSystemNode & globalEffects)
auto addBonusForTier = [&](int tier, std::shared_ptr<Bonus> b) { auto addBonusForTier = [&](int tier, std::shared_ptr<Bonus> b) {
assert(vstd::iswithin(tier, 1, 7)); assert(vstd::iswithin(tier, 1, 7));
//bonuses from level 7 are given to high-level creatures too //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); auto limiter = std::make_shared<CreatureLevelLimiter>(tier, max);
b->addLimiter(limiter); b->addLimiter(limiter);
globalEffects.addNewBonus(b); globalEffects.addNewBonus(b);

View File

@ -280,6 +280,7 @@ public:
enum Type enum Type
{ {
DEFAULT = -50, DEFAULT = -50,
HORDE_PLACEHOLDER8 = -37,
HORDE_PLACEHOLDER7 = -36, HORDE_PLACEHOLDER7 = -36,
HORDE_PLACEHOLDER6 = -35, HORDE_PLACEHOLDER6 = -35,
HORDE_PLACEHOLDER5 = -34, HORDE_PLACEHOLDER5 = -34,
@ -297,7 +298,7 @@ public:
HORDE_2_UPGR, GRAIL, EXTRA_TOWN_HALL, EXTRA_CITY_HALL, EXTRA_CAPITOL, 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_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_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_1 = DWELL_FIRST,
DWELL_LVL_7 = DWELL_LAST, 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 bool IsSpecialOrGrail() const
{ {
return num == SPECIAL_1 || num == SPECIAL_2 || num == SPECIAL_3 || num == SPECIAL_4 || num == GRAIL; return num == SPECIAL_1 || num == SPECIAL_2 || num == SPECIAL_3 || num == SPECIAL_4 || num == GRAIL;

View File

@ -22,7 +22,7 @@ namespace GameConstants
constexpr int ALL_PLAYERS = 255; //bitfield 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_LEVELS = 5;
constexpr int SPELL_SCHOOL_LEVELS = 4; constexpr int SPELL_SCHOOL_LEVELS = 4;
constexpr int DEFAULT_SCHOOLS = 4; constexpr int DEFAULT_SCHOOLS = 4;

View File

@ -56,7 +56,7 @@ namespace NSecondarySkill
namespace EBuildingType namespace EBuildingType
{ {
const std::string names [44] = const std::string names [46] =
{ {
"mageGuild1", "mageGuild2", "mageGuild3", "mageGuild4", "mageGuild5", // 5 "mageGuild1", "mageGuild2", "mageGuild3", "mageGuild4", "mageGuild5", // 5
"tavern", "shipyard", "fort", "citadel", "castle", // 10 "tavern", "shipyard", "fort", "citadel", "castle", // 10
@ -66,7 +66,8 @@ namespace EBuildingType
"horde2Upgr", "grail", "extraTownHall", "extraCityHall", "extraCapitol", // 30 "horde2Upgr", "grail", "extraTownHall", "extraCityHall", "extraCapitol", // 30
"dwellingLvl1", "dwellingLvl2", "dwellingLvl3", "dwellingLvl4", "dwellingLvl5", // 35 "dwellingLvl1", "dwellingLvl2", "dwellingLvl3", "dwellingLvl4", "dwellingLvl5", // 35
"dwellingLvl6", "dwellingLvl7", "dwellingUpLvl1", "dwellingUpLvl2", "dwellingUpLvl3", // 40 "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 }, { "dwellingLvl5", BuildingID::DWELL_LVL_5 },
{ "dwellingLvl6", BuildingID::DWELL_LVL_6 }, { "dwellingLvl6", BuildingID::DWELL_LVL_6 },
{ "dwellingLvl7", BuildingID::DWELL_LVL_7 }, { "dwellingLvl7", BuildingID::DWELL_LVL_7 },
{ "dwellingLvl8", BuildingID::DWELL_LVL_8 },
{ "dwellingUpLvl1", BuildingID::DWELL_LVL_1_UP }, { "dwellingUpLvl1", BuildingID::DWELL_LVL_1_UP },
{ "dwellingUpLvl2", BuildingID::DWELL_LVL_2_UP }, { "dwellingUpLvl2", BuildingID::DWELL_LVL_2_UP },
{ "dwellingUpLvl3", BuildingID::DWELL_LVL_3_UP }, { "dwellingUpLvl3", BuildingID::DWELL_LVL_3_UP },
@ -170,6 +172,7 @@ namespace MappedKeys
{ "dwellingUpLvl5", BuildingID::DWELL_LVL_5_UP }, { "dwellingUpLvl5", BuildingID::DWELL_LVL_5_UP },
{ "dwellingUpLvl6", BuildingID::DWELL_LVL_6_UP }, { "dwellingUpLvl6", BuildingID::DWELL_LVL_6_UP },
{ "dwellingUpLvl7", BuildingID::DWELL_LVL_7_UP }, { "dwellingUpLvl7", BuildingID::DWELL_LVL_7_UP },
{ "dwellingUpLvl8", BuildingID::DWELL_LVL_8_UP },
}; };
static const std::map<std::string, BuildingSubID::EBuildingSubID> SPECIAL_BUILDINGS = static const std::map<std::string, BuildingSubID::EBuildingSubID> SPECIAL_BUILDINGS =

View File

@ -9,6 +9,9 @@
*/ */
#include "StdInc.h" #include "StdInc.h"
#include "CBuildingHandler.h" #include "CBuildingHandler.h"
#include "VCMI_Lib.h"
#include "../faction/CTown.h"
#include "../faction/CTownHandler.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -36,7 +39,7 @@ BuildingID CBuildingHandler::campToERMU(int camp, FactionID townType, const std:
}; };
int curPos = static_cast<int>(campToERMU.size()); 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 if(camp == curPos) //non-upgraded
return BuildingID(30 + i); return BuildingID(30 + i);
@ -53,7 +56,7 @@ BuildingID CBuildingHandler::campToERMU(int camp, FactionID townType, const std:
{ {
if (hordeLvlsPerTType[townType.getNum()][0] == i) 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 if(vstd::contains(builtBuildings, dwellingID)) //if upgraded dwelling is built
return BuildingID::HORDE_1_UPGR; return BuildingID::HORDE_1_UPGR;
@ -64,7 +67,7 @@ BuildingID CBuildingHandler::campToERMU(int camp, FactionID townType, const std:
{ {
if(hordeLvlsPerTType[townType.getNum()].size() > 1) 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 if(vstd::contains(builtBuildings, dwellingID)) //if upgraded dwelling is built
return BuildingID::HORDE_2_UPGR; return BuildingID::HORDE_2_UPGR;

View File

@ -795,10 +795,11 @@ void CGameState::initTowns()
for (auto & vti : map->towns) for (auto & vti : map->towns)
{ {
assert(vti->town); 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 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 }; 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 }; 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 //init buildings
if(vstd::contains(vti->builtBuildings, BuildingID::DEFAULT)) //give standard set of 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); vti->builtBuildings.insert(BuildingID::VILLAGE_HALL);
//init hordes //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 if (vstd::contains(vti->builtBuildings, hordes[i])) //if we have horde for this level
{ {
@ -863,7 +864,7 @@ void CGameState::initTowns()
//town events //town events
for(CCastleEvent &ev : vti->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 if (vstd::contains(ev.buildings,hordes[i])) //if we have horde for this level
{ {
ev.buildings.erase(hordes[i]); ev.buildings.erase(hordes[i]);

View File

@ -128,7 +128,7 @@ GrowthInfo CGTownInstance::getGrowthInfo(int level) const
{ {
GrowthInfo ret; GrowthInfo ret;
if (level<0 || level >=GameConstants::CREATURES_PER_TOWN) if (level<0 || level >=town->creatures.size())
return ret; return ret;
if (creatures[level].second.empty()) if (creatures[level].second.empty())
return ret; //no dwelling return ret; //no dwelling
@ -514,16 +514,16 @@ void CGTownInstance::initObj(vstd::RNG & rand) ///initialize town structures
blockVisit = true; blockVisit = true;
if(townEnvisagesBuilding(BuildingSubID::PORTAL_OF_SUMMONING)) //Dungeon for example if(townEnvisagesBuilding(BuildingSubID::PORTAL_OF_SUMMONING)) //Dungeon for example
creatures.resize(GameConstants::CREATURES_PER_TOWN + 1); creatures.resize(town->creatures.size() + 1);
else 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; 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) if (hasBuilt(buildID) && town->creatures.at(level).size() > upgradeNum)
creatures[level].second.push_back(town->creatures[level][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 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()) if (!town->creatures[i].empty())
{ {
CreatureID c = town->creatures[i][0]; CreatureID c = town->creatures[i][0];

View File

@ -57,6 +57,7 @@ std::string defaultBuildingIdConversion(BuildingID bId)
case BuildingID::DWELL_LVL_5: return "DWELL_LVL_5"; case BuildingID::DWELL_LVL_5: return "DWELL_LVL_5";
case BuildingID::DWELL_LVL_6: return "DWELL_LVL_6"; case BuildingID::DWELL_LVL_6: return "DWELL_LVL_6";
case BuildingID::DWELL_LVL_7: return "DWELL_LVL_7"; 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_1_UP: return "DWELL_LVL_1_UP";
case BuildingID::DWELL_LVL_2_UP: return "DWELL_LVL_2_UP"; case BuildingID::DWELL_LVL_2_UP: return "DWELL_LVL_2_UP";
case BuildingID::DWELL_LVL_3_UP: return "DWELL_LVL_3_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_5_UP: return "DWELL_LVL_5_UP";
case BuildingID::DWELL_LVL_6_UP: return "DWELL_LVL_6_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_7_UP: return "DWELL_LVL_7_UP";
case BuildingID::DWELL_LVL_8_UP: return "DWELL_LVL_8_UP";
default: default:
return "UNKNOWN"; return "UNKNOWN";
} }

View File

@ -599,12 +599,12 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
return; 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; SetAvailableCreatures ssi;
ssi.tid = town->id; ssi.tid = town->id;
ssi.creatures = town->creatures; 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; const std::vector<ConstTransitivePtr<CGDwelling> > &dwellings = p->dwellings;
if (dwellings.empty())//no dwellings - just remove if (dwellings.empty())//no dwellings - just remove
@ -620,13 +620,13 @@ void CGameHandler::setPortalDwelling(const CGTownInstance * town, bool forced=fa
if (clear) 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 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); sendAndApply(&ssi);
} }
} }
@ -877,7 +877,7 @@ void CGameHandler::onNewTurn()
} }
auto & sac = n.cres.at(t->id); 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 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 if(buildingID >= BuildingID::DWELL_FIRST) //dwelling
{ {
int level = (buildingID - BuildingID::DWELL_FIRST) % GameConstants::CREATURES_PER_TOWN; int level = BuildingID::getLevelFromDwelling(buildingID);
int upgradeNumber = (buildingID - BuildingID::DWELL_FIRST) / GameConstants::CREATURES_PER_TOWN; int upgradeNumber = BuildingID::getUpgradedFromDwelling(buildingID);
if(upgradeNumber >= t->town->creatures.at(level).size()) if(upgradeNumber >= t->town->creatures.at(level).size())
{ {