1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +02:00

- creatures availability tests no longer check for built buildings.

Fixes #1650
- do not crash if town has 0 creatures on some dwelling level
- do not crash if dwelling for some level is not present in town at all
This commit is contained in:
Ivan Savenko 2014-01-11 18:12:09 +00:00
parent bc1e726be4
commit fb5c9fc972
6 changed files with 98 additions and 69 deletions

View File

@ -1467,7 +1467,7 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
}
else
buildingID = BuildingID::SPECIAL_3;
recAreas.push_back(new RecruitArea(positions[i].x, positions[i].y, town, buildingID, i));
recAreas.push_back(new RecruitArea(positions[i].x, positions[i].y, town, i));
}
resdatabar = new CMinorResDataBar;
@ -1529,7 +1529,36 @@ void LabeledValue::hover(bool on)
}
}
CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *Town, BuildingID buildingID, int Level):
const CCreature * CFortScreen::RecruitArea::getMyCreature()
{
if (!town->creatures.at(level).second.empty()) // built
return VLC->creh->creatures[town->creatures.at(level).second.back()];
if (!town->town->creatures.at(level).empty()) // there are creatures on this level
return VLC->creh->creatures[town->town->creatures.at(level).front()];
return nullptr;
}
const CBuilding * CFortScreen::RecruitArea::getMyBuilding()
{
BuildingID myID = BuildingID(BuildingID::DWELL_FIRST).advance(level);
if (level == GameConstants::CREATURES_PER_TOWN)
return town->town->buildings.at(BuildingID::PORTAL_OF_SUMMON);
if (!town->town->buildings.count(myID))
return nullptr;
const CBuilding * build = town->town->buildings.at(myID);
while (town->town->buildings.count(myID))
{
if (town->hasBuilt(myID))
build = town->town->buildings.at(myID);
myID.advance(GameConstants::CREATURES_PER_TOWN);
}
return build;
}
CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *Town, int Level):
town(Town),
level(Level),
availableCount(nullptr)
@ -1544,39 +1573,37 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *
addUsedEvents(LCLICK | RCLICK | HOVER);//Activate only if dwelling is present
icons = new CPicture("TPCAINFO", 261, 3);
buildingPic = new CAnimImage(town->town->clientInfo.buildingsIcons, buildingID, 0, 4, 21);
const CCreature* creature = nullptr;
if (!town->creatures[level].second.empty())
creature = CGI->creh->creatures[town->creatures[level].second.back()];
else
creature = CGI->creh->creatures[town->town->creatures[level][0]];
hoverText = boost::str(boost::format(CGI->generaltexth->tcommands[21]) % creature->namePl);
creatureAnim = new CCreaturePic(159, 4, creature, false);
Rect sizes(287, 4, 96, 18);
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[190], CGI->generaltexth->fcommands[0], creature->Attack()));
sizes.y+=20;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[191], CGI->generaltexth->fcommands[1], creature->Defense()));
sizes.y+=21;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[199], CGI->generaltexth->fcommands[2], creature->getMinDamage(), creature->getMaxDamage()));
sizes.y+=20;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[388], CGI->generaltexth->fcommands[3], creature->MaxHealth()));
sizes.y+=21;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[193], CGI->generaltexth->fcommands[4], creature->valOfBonuses(Bonus::STACKS_SPEED)));
sizes.y+=20;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[194], CGI->generaltexth->fcommands[5], town->creatureGrowth(level)));
creatureName = new CLabel(78, 11, FONT_SMALL, CENTER, Colors::WHITE, creature->namePl);
dwellingName = new CLabel(78, 101, FONT_SMALL, CENTER, Colors::WHITE, town->town->buildings.at(buildingID)->Name());
if (vstd::contains(town->builtBuildings, buildingID))
if (getMyBuilding() != nullptr)
{
ui32 available = town->creatures[level].first;
std::string availableText = CGI->generaltexth->allTexts[217]+ boost::lexical_cast<std::string>(available);
availableCount = new CLabel(78, 119, FONT_SMALL, CENTER, Colors::WHITE, availableText);
buildingPic = new CAnimImage(town->town->clientInfo.buildingsIcons, getMyBuilding()->bid, 0, 4, 21);
dwellingName = new CLabel(78, 101, FONT_SMALL, CENTER, Colors::WHITE, getMyBuilding()->Name());
if (vstd::contains(town->builtBuildings, getMyBuilding()->bid))
{
ui32 available = town->creatures[level].first;
std::string availableText = CGI->generaltexth->allTexts[217]+ boost::lexical_cast<std::string>(available);
availableCount = new CLabel(78, 119, FONT_SMALL, CENTER, Colors::WHITE, availableText);
}
}
if (getMyCreature() != nullptr)
{
hoverText = boost::str(boost::format(CGI->generaltexth->tcommands[21]) % getMyCreature()->namePl);
creatureAnim = new CCreaturePic(159, 4, getMyCreature(), false);
creatureName = new CLabel(78, 11, FONT_SMALL, CENTER, Colors::WHITE, getMyCreature()->namePl);
Rect sizes(287, 4, 96, 18);
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[190], CGI->generaltexth->fcommands[0], getMyCreature()->Attack()));
sizes.y+=20;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[191], CGI->generaltexth->fcommands[1], getMyCreature()->Defense()));
sizes.y+=21;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[199], CGI->generaltexth->fcommands[2], getMyCreature()->getMinDamage(), getMyCreature()->getMaxDamage()));
sizes.y+=20;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[388], CGI->generaltexth->fcommands[3], getMyCreature()->MaxHealth()));
sizes.y+=21;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[193], CGI->generaltexth->fcommands[4], getMyCreature()->valOfBonuses(Bonus::STACKS_SPEED)));
sizes.y+=20;
values.push_back(new LabeledValue(sizes, CGI->generaltexth->allTexts[194], CGI->generaltexth->fcommands[5], town->creatureGrowth(level)));
}
}

View File

@ -315,8 +315,10 @@ class CFortScreen : public CWindowObject
CAnimImage * buildingPic;
CCreaturePic *creatureAnim;
const CCreature * getMyCreature();
const CBuilding * getMyBuilding();
public:
RecruitArea(int posX, int posY, const CGTownInstance *town, BuildingID buildingID, int level);
RecruitArea(int posX, int posY, const CGTownInstance *town, int level);
void creaturesChanged();
void hover(bool on);

View File

@ -2862,7 +2862,10 @@ void OptionsTab::CPregameTooltipBox::genTownWindow()
const CTown * town = CGI->townh->factions[settings.castle]->town;
for (auto & elem : town->creatures)
components.push_back(new CComponent(CComponent::creature, elem.front(), 0, CComponent::tiny));
{
if (!elem.empty())
components.push_back(new CComponent(CComponent::creature, elem.front(), 0, CComponent::tiny));
}
new CComponentBox(components, Rect(10, 140, pos.w - 20, 140));
}

View File

@ -344,7 +344,7 @@ std::set<int3> CGObjectInstance::getBlockedPos() const
{
for(int h=0; h<getHeight(); ++h)
{
if (appearance.isBlockedAt(-w, -h))
if (appearance.isBlockedAt(w, h))
ret.insert(int3(pos.x - w, pos.y - h, pos.z));
}
}
@ -2050,20 +2050,11 @@ int CGTownInstance::mageGuildLevel() const
return 0;
}
int CGTownInstance::creatureDwellingLevel(int dwelling) const
{
if ( dwelling<0 || dwelling >= GameConstants::CREATURES_PER_TOWN )
return -1;
for (int i=0; ; i++)
{
if (!hasBuilt(BuildingID(BuildingID::DWELL_FIRST+dwelling+i*GameConstants::CREATURES_PER_TOWN)))
return i-1;
}
}
int CGTownInstance::getHordeLevel(const int & HID) const//HID - 0 or 1; returns creature level or -1 if that horde structure is not present
{
return town->hordeLvl.at(HID);
}
int CGTownInstance::creatureGrowth(const int & level) const
{
return getGrowthInfo(level).totalGrowth();
@ -2243,12 +2234,16 @@ void CGTownInstance::initObj()
creatures.resize(GameConstants::CREATURES_PER_TOWN+1);//extra dwelling for Dungeon
else
creatures.resize(GameConstants::CREATURES_PER_TOWN);
for (int i = 0; i < GameConstants::CREATURES_PER_TOWN; i++)
for (int level = 0; level < GameConstants::CREATURES_PER_TOWN; level++)
{
int dwellingLevel = creatureDwellingLevel(i);
int creaturesTotal = town->creatures[i].size();
for (int j=0; j< std::min(dwellingLevel + 1, creaturesTotal); j++)
creatures[i].second.push_back(town->creatures[i][j]);
BuildingID buildID = BuildingID(BuildingID::DWELL_FIRST).advance(level);
int upgradeNum = 0;
for (; town->buildings.count(buildID); upgradeNum++, buildID.advance(GameConstants::CREATURES_PER_TOWN))
{
if (hasBuilt(buildID) && town->creatures.at(level).size() > upgradeNum)
creatures[level].second.push_back(town->creatures[level][upgradeNum]);
}
}
switch (subID)
@ -2321,23 +2316,26 @@ void CGTownInstance::newTurn() const
}
if ((stacksCount() < GameConstants::ARMY_SIZE && rand()%100 < 25) || Slots().empty()) //add new stack
{
int i = rand() % std::min (GameConstants::ARMY_SIZE, cb->getDate(Date::MONTH)<<1);
CreatureID c = town->creatures[i][0];
SlotID n;
int i = rand() % std::min (GameConstants::CREATURES_PER_TOWN, cb->getDate(Date::MONTH)<<1);
if (!town->creatures[i].empty())
{
CreatureID c = town->creatures[i][0];
SlotID n;
TQuantity count = creatureGrowth(i);
if (!count) // no dwelling
count = VLC->creh->creatures[c]->growth;
TQuantity count = creatureGrowth(i);
if (!count) // no dwelling
count = VLC->creh->creatures[c]->growth;
{//no lower tiers or above current month
{//no lower tiers or above current month
if ((n = getSlotFor(c)).validSlot())
{
StackLocation sl(this, n);
if (slotEmpty(n))
cb->insertNewStack(sl, VLC->creh->creatures[c], count);
else //add to existing
cb->changeStackCount(sl, count);
if ((n = getSlotFor(c)).validSlot())
{
StackLocation sl(this, n);
if (slotEmpty(n))
cb->insertNewStack(sl, VLC->creh->creatures[c], count);
else //add to existing
cb->changeStackCount(sl, count);
}
}
}
}

View File

@ -694,7 +694,6 @@ public:
CGTownInstance::EFortLevel fortLevel() const;
int hallLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
int mageGuildLevel() const; // -1 - none, 0 - village, 1 - town, 2 - city, 3 - capitol
int creatureDwellingLevel(int dwelling) const;
int getHordeLevel(const int & HID) const; //HID - 0 or 1; returns creature level or -1 if that horde structure is not present
int creatureGrowth(const int & level) const;
GrowthInfo getGrowthInfo(int level) const;

View File

@ -1290,7 +1290,7 @@ void CGameHandler::newTurn()
for (int k=0; k < GameConstants::CREATURES_PER_TOWN; k++) //creature growths
{
if(t->creatureDwellingLevel(k) >= 0)//there is dwelling (k-level)
if (!t->creatures.at(k).second.empty()) // there are creatures at this level
{
ui32 &availableCount = sac.creatures.at(k).first;
const CCreature *cre = VLC->creh->creatures.at(t->creatures.at(k).second.back());
@ -4853,7 +4853,7 @@ void CGameHandler::handleTownEvents(CGTownInstance * town, NewTurn &n)
for(si32 i=0;i<ev.creatures.size();i++) //creature growths
{
if(town->creatureDwellingLevel(i) >= 0 && ev.creatures.at(i))//there is dwelling
if(!town->creatures.at(i).second.empty() && ev.creatures.at(i) > 0)//there is dwelling
{
sac.creatures[i].first += ev.creatures.at(i);
iw.components.push_back(Component(Component::CREATURE,