|
@@ -40,13 +40,13 @@ using namespace boost::assign;
|
|
|
const CBuilding * CBuildingRect::getBuilding()
|
|
|
{
|
|
|
if (!str->building)
|
|
|
- return nullptr;
|
|
|
-
|
|
|
- if (str->hiddenUpgrade) // hidden upgrades, e.g. hordes - return base (dwelling for hordes)
|
|
|
- return town->town->buildings.at(str->building->getBase());
|
|
|
-
|
|
|
- return str->building;
|
|
|
-}
|
|
|
+ return nullptr;
|
|
|
+
|
|
|
+ if (str->hiddenUpgrade) // hidden upgrades, e.g. hordes - return base (dwelling for hordes)
|
|
|
+ return town->town->buildings.at(str->building->getBase());
|
|
|
+
|
|
|
+ return str->building;
|
|
|
+}
|
|
|
|
|
|
CBuildingRect::CBuildingRect(CCastleBuildings * Par, const CGTownInstance *Town, const CStructure *Str)
|
|
|
:CShowableAnim(0, 0, Str->defName, CShowableAnim::BASE | CShowableAnim::USE_RLE),
|
|
@@ -114,13 +114,13 @@ void CBuildingRect::clickRight(tribool down, bool previousState)
|
|
|
{
|
|
|
if((!area) || (!((bool)down)) || (this!=parent->selectedBuilding) || getBuilding() == nullptr)
|
|
|
return;
|
|
|
- if( !CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image
|
|
|
- {
|
|
|
- BuildingID bid = getBuilding()->bid;
|
|
|
- const CBuilding *bld = town->town->buildings.at(bid);
|
|
|
- if (bid < BuildingID::DWELL_FIRST)
|
|
|
- {
|
|
|
- CRClickPopup::createAndPush(CInfoWindow::genText(bld->Name(), bld->Description()),
|
|
|
+ if( !CSDL_Ext::isTransparent(area, GH.current->motion.x-pos.x, GH.current->motion.y-pos.y) ) //inside building image
|
|
|
+ {
|
|
|
+ BuildingID bid = getBuilding()->bid;
|
|
|
+ const CBuilding *bld = town->town->buildings.at(bid);
|
|
|
+ if (bid < BuildingID::DWELL_FIRST)
|
|
|
+ {
|
|
|
+ CRClickPopup::createAndPush(CInfoWindow::genText(bld->Name(), bld->Description()),
|
|
|
new CComponent(CComponent::building, bld->town->faction->index, bld->bid));
|
|
|
}
|
|
|
else
|
|
@@ -209,20 +209,20 @@ std::string CBuildingRect::getSubtitle()//hover text for building
|
|
|
if (!getBuilding())
|
|
|
return "";
|
|
|
|
|
|
- int bid = getBuilding()->bid;
|
|
|
-
|
|
|
- if (bid<30)//non-dwellings - only buiding name
|
|
|
- return town->town->buildings.at(getBuilding()->bid)->Name();
|
|
|
- else//dwellings - recruit %creature%
|
|
|
- {
|
|
|
- auto & availableCreatures = town->creatures[(bid-30)%GameConstants::CREATURES_PER_TOWN].second;
|
|
|
- if(availableCreatures.size())
|
|
|
- {
|
|
|
- int creaID = availableCreatures.back();//taking last of available creatures
|
|
|
- return CGI->generaltexth->allTexts[16] + " " + CGI->creh->creatures.at(creaID)->namePl;
|
|
|
- }
|
|
|
- else
|
|
|
- {
|
|
|
+ int bid = getBuilding()->bid;
|
|
|
+
|
|
|
+ if (bid<30)//non-dwellings - only buiding name
|
|
|
+ return town->town->buildings.at(getBuilding()->bid)->Name();
|
|
|
+ else//dwellings - recruit %creature%
|
|
|
+ {
|
|
|
+ auto & availableCreatures = town->creatures[(bid-30)%GameConstants::CREATURES_PER_TOWN].second;
|
|
|
+ if(availableCreatures.size())
|
|
|
+ {
|
|
|
+ int creaID = availableCreatures.back();//taking last of available creatures
|
|
|
+ return CGI->generaltexth->allTexts[16] + " " + CGI->creh->creatures.at(creaID)->namePl;
|
|
|
+ }
|
|
|
+ else
|
|
|
+ {
|
|
|
logGlobal->warnStream() << "Problem: dwelling with id " << bid << " offers no creatures!";
|
|
|
return "#ERROR#";
|
|
|
}
|
|
@@ -255,18 +255,18 @@ void CBuildingRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
|
|
|
|
|
|
CDwellingInfoBox::CDwellingInfoBox(int centerX, int centerY, const CGTownInstance *Town, int level):
|
|
|
CWindowObject(RCLICK_POPUP | PLAYER_COLORED, "CRTOINFO", Point(centerX, centerY))
|
|
|
-{
|
|
|
- OBJ_CONSTRUCTION_CAPTURING_ALL;
|
|
|
-
|
|
|
- const CCreature * creature = CGI->creh->creatures.at(Town->creatures.at(level).second.back());
|
|
|
-
|
|
|
- title = new CLabel(80, 30, FONT_SMALL, CENTER, Colors::WHITE, creature->namePl);
|
|
|
- animation = new CCreaturePic(30, 44, creature, true, true);
|
|
|
-
|
|
|
- std::string text = boost::lexical_cast<std::string>(Town->creatures.at(level).first);
|
|
|
- available = new CLabel(80,190, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[217] + text);
|
|
|
- costPerTroop = new CLabel(80, 227, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[346]);
|
|
|
-
|
|
|
+{
|
|
|
+ OBJ_CONSTRUCTION_CAPTURING_ALL;
|
|
|
+
|
|
|
+ const CCreature * creature = CGI->creh->creatures.at(Town->creatures.at(level).second.back());
|
|
|
+
|
|
|
+ title = new CLabel(80, 30, FONT_SMALL, CENTER, Colors::WHITE, creature->namePl);
|
|
|
+ animation = new CCreaturePic(30, 44, creature, true, true);
|
|
|
+
|
|
|
+ std::string text = boost::lexical_cast<std::string>(Town->creatures.at(level).first);
|
|
|
+ available = new CLabel(80,190, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[217] + text);
|
|
|
+ costPerTroop = new CLabel(80, 227, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[346]);
|
|
|
+
|
|
|
for(int i = 0; i<GameConstants::RESOURCE_QUANTITY; i++)
|
|
|
{
|
|
|
if(creature->cost[i])
|
|
@@ -503,13 +503,13 @@ void CCastleBuildings::recreate()
|
|
|
groups[structure->building->getBase()].push_back(structure);
|
|
|
}
|
|
|
}
|
|
|
-
|
|
|
- for(auto & entry : groups)
|
|
|
- {
|
|
|
- const CBuilding * build = town->town->buildings.at(entry.first);
|
|
|
-
|
|
|
- const CStructure * toAdd = *boost::max_element(entry.second, [=](const CStructure * a, const CStructure * b)
|
|
|
- {
|
|
|
+
|
|
|
+ for(auto & entry : groups)
|
|
|
+ {
|
|
|
+ const CBuilding * build = town->town->buildings.at(entry.first);
|
|
|
+
|
|
|
+ const CStructure * toAdd = *boost::max_element(entry.second, [=](const CStructure * a, const CStructure * b)
|
|
|
+ {
|
|
|
return build->getDistance(a->building->bid)
|
|
|
< build->getDistance(b->building->bid);
|
|
|
});
|
|
@@ -526,17 +526,17 @@ CCastleBuildings::~CCastleBuildings()
|
|
|
{
|
|
|
}
|
|
|
|
|
|
-void CCastleBuildings::addBuilding(BuildingID building)
|
|
|
-{
|
|
|
- //FIXME: implement faster method without complete recreation of town
|
|
|
- BuildingID base = town->town->buildings.at(building)->getBase();
|
|
|
-
|
|
|
- recreate();
|
|
|
-
|
|
|
- auto & structures = groups.at(base);
|
|
|
-
|
|
|
- for(CBuildingRect * rect : buildings)
|
|
|
- {
|
|
|
+void CCastleBuildings::addBuilding(BuildingID building)
|
|
|
+{
|
|
|
+ //FIXME: implement faster method without complete recreation of town
|
|
|
+ BuildingID base = town->town->buildings.at(building)->getBase();
|
|
|
+
|
|
|
+ recreate();
|
|
|
+
|
|
|
+ auto & structures = groups.at(base);
|
|
|
+
|
|
|
+ for(CBuildingRect * rect : buildings)
|
|
|
+ {
|
|
|
if (vstd::contains(structures, rect->str))
|
|
|
{
|
|
|
//reset animation
|
|
@@ -1111,13 +1111,13 @@ CTownInfo::CTownInfo(int posX, int posY, const CGTownInstance* Town, bool townHa
|
|
|
{
|
|
|
buildID = 6 + town->fortLevel();
|
|
|
if (buildID == 6)
|
|
|
- return;
|
|
|
- picture = new CAnimImage("ITMCL.DEF", town->fortLevel()-1);
|
|
|
- }
|
|
|
- building = town->town->buildings.at(BuildingID(buildID));
|
|
|
- pos = picture->pos;
|
|
|
-}
|
|
|
-
|
|
|
+ return;
|
|
|
+ picture = new CAnimImage("ITMCL.DEF", town->fortLevel()-1);
|
|
|
+ }
|
|
|
+ building = town->town->buildings.at(BuildingID(buildID));
|
|
|
+ pos = picture->pos;
|
|
|
+}
|
|
|
+
|
|
|
void CTownInfo::hover(bool on)
|
|
|
{
|
|
|
if(on)
|
|
@@ -1238,7 +1238,7 @@ void CHallInterface::CBuildingBox::hover(bool on)
|
|
|
if(on)
|
|
|
{
|
|
|
std::string toPrint;
|
|
|
- if(state==EBuildingState::PREREQUIRES)
|
|
|
+ if(state==EBuildingState::PREREQUIRES || state == EBuildingState::MISSING_BASE)
|
|
|
toPrint = CGI->generaltexth->hcommands[5];
|
|
|
else if(state==EBuildingState::CANT_BUILD_TODAY)
|
|
|
toPrint = CGI->generaltexth->allTexts[223];
|
|
@@ -1276,8 +1276,8 @@ CHallInterface::CBuildingBox::CBuildingBox(int x, int y, const CGTownInstance *
|
|
|
|
|
|
state = LOCPLINT->cb->canBuildStructure(town,building->bid);
|
|
|
assert(state < EBuildingState::BUILDING_ERROR);
|
|
|
- static int panelIndex[9] = { 3, 3, 3, 0, 0, 2, 2, 1, 2};
|
|
|
- static int iconIndex[9] = {-1, -1, -1, 0, 0, 1, 2, -1, 1};
|
|
|
+ static int panelIndex[10] = { 3, 3, 3, 0, 0, 2, 2, 1, 2, 2};
|
|
|
+ static int iconIndex[10] = {-1, -1, -1, 0, 0, 1, 2, -1, 1, 1};
|
|
|
|
|
|
picture = new CAnimImage(town->town->clientInfo.buildingsIcons, building->bid, 0, 2, 2);
|
|
|
panel = new CAnimImage("TPTHBAR", panelIndex[state], 0, 1, 73);
|
|
@@ -1295,13 +1295,13 @@ CHallInterface::CHallInterface(const CGTownInstance *Town):
|
|
|
resdatabar = new CMinorResDataBar;
|
|
|
resdatabar->pos.x += pos.x;
|
|
|
resdatabar->pos.y += pos.y;
|
|
|
- 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.at(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);
|
|
|
+ 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.at(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);
|
|
|
|
|
|
auto & boxList = town->town->clientInfo.hallSlots;
|
|
|
boxes.resize(boxList.size());
|
|
@@ -1310,13 +1310,13 @@ CHallInterface::CHallInterface(const CGTownInstance *Town):
|
|
|
for(size_t col=0; col<boxList[row].size(); col++) //for each box
|
|
|
{
|
|
|
const CBuilding *building = nullptr;
|
|
|
- for(auto & elem : boxList[row][col])//we are looking for the first not build structure
|
|
|
- {
|
|
|
- auto buildingID = elem;
|
|
|
- building = town->town->buildings.at(buildingID);
|
|
|
-
|
|
|
- if(!vstd::contains(town->builtBuildings,buildingID))
|
|
|
- break;
|
|
|
+ for(auto & elem : boxList[row][col])//we are looking for the first not build structure
|
|
|
+ {
|
|
|
+ auto buildingID = elem;
|
|
|
+ building = town->town->buildings.at(buildingID);
|
|
|
+
|
|
|
+ if(!vstd::contains(town->builtBuildings,buildingID))
|
|
|
+ break;
|
|
|
}
|
|
|
int posX = pos.w/2 - boxList[row].size()*154/2 - (boxList[row].size()-1)*20 + 194*col,
|
|
|
posY = 35 + 104*row;
|
|
@@ -1336,28 +1336,38 @@ void CBuildWindow::buyFunc()
|
|
|
std::string CBuildWindow::getTextForState(int state)
|
|
|
{
|
|
|
std::string ret;
|
|
|
- if(state<7)
|
|
|
+ if(state < EBuildingState::ALLOWED)
|
|
|
ret = CGI->generaltexth->hcommands[state];
|
|
|
switch (state)
|
|
|
{
|
|
|
- case 4: case 5: case 6:
|
|
|
- ret.replace(ret.find_first_of("%s"),2,building->Name());
|
|
|
+ case EBuildingState::ALREADY_PRESENT:
|
|
|
+ case EBuildingState::CANT_BUILD_TODAY:
|
|
|
+ case EBuildingState::NO_RESOURCES:
|
|
|
+ ret.replace(ret.find_first_of("%s"), 2, building->Name());
|
|
|
break;
|
|
|
- case 7:
|
|
|
+ case EBuildingState::ALLOWED:
|
|
|
return CGI->generaltexth->allTexts[219]; //all prereq. are met
|
|
|
- case 8:
|
|
|
+ case EBuildingState::PREREQUIRES:
|
|
|
{
|
|
|
+ auto toStr = [&](const BuildingID build) -> std::string
|
|
|
+ {
|
|
|
+ return town->town->buildings.at(build)->Name();
|
|
|
+ };
|
|
|
+ /*auto toBool = [&](const BuildingID build)
|
|
|
+ {
|
|
|
+ return town->hasBuilt(build);
|
|
|
+ };*/
|
|
|
+
|
|
|
ret = CGI->generaltexth->allTexts[52];
|
|
|
- std::set<BuildingID> reqs= LOCPLINT->cb->getBuildingRequiments(town, building->bid);
|
|
|
-
|
|
|
- for(const auto & i : reqs)
|
|
|
- {
|
|
|
- if (vstd::contains(town->builtBuildings, i))
|
|
|
- continue;//skipping constructed buildings
|
|
|
- ret+= town->town->buildings.at(i)->Name() + ", ";
|
|
|
- }
|
|
|
- ret.erase(ret.size()-2);
|
|
|
- }
|
|
|
+ ret += "\n" + building->requirements.toString(toStr);
|
|
|
+ break;
|
|
|
+ }
|
|
|
+ case EBuildingState::MISSING_BASE:
|
|
|
+ {
|
|
|
+ std::string msg = CGI->generaltexth->localizedTexts["townHall"]["missingBase"].String();
|
|
|
+ ret = boost::str(boost::format(msg) % town->town->buildings.at(building->upgrade)->Name());
|
|
|
+ break;
|
|
|
+ }
|
|
|
}
|
|
|
return ret;
|
|
|
}
|
|
@@ -1423,13 +1433,13 @@ CFortScreen::CFortScreen(const CGTownInstance * town):
|
|
|
{
|
|
|
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
|
|
ui32 fortSize = town->creatures.size();
|
|
|
- if (fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty())
|
|
|
- fortSize--;
|
|
|
-
|
|
|
- const CBuilding *fortBuilding = town->town->buildings.at(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());
|
|
|
+ if (fortSize > GameConstants::CREATURES_PER_TOWN && town->creatures.back().second.empty())
|
|
|
+ fortSize--;
|
|
|
+
|
|
|
+ const CBuilding *fortBuilding = town->town->buildings.at(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());
|
|
|
exit = new CAdventureMapButton(text, "", boost::bind(&CFortScreen::close,this) ,748, 556, "TPMAGE1", SDLK_RETURN);
|
|
|
exit->assignedKeys.insert(SDLK_ESCAPE);
|
|
|
|
|
@@ -1555,13 +1565,13 @@ CFortScreen::RecruitArea::RecruitArea(int posX, int posY, const CGTownInstance *
|
|
|
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))
|
|
|
- {
|
|
|
+ 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))
|
|
|
+ {
|
|
|
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);
|