mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
- handling of incorrect or missing configuration files (settings.json\defaultSettings.json)
- better code for recruitment window, fixes #1013 - minor tweak to adv.map classes
This commit is contained in:
parent
933049ee91
commit
770a6e077c
@ -247,7 +247,7 @@ void CHeroList::update(const CGHeroInstance * hero)
|
||||
for (auto iter = list->getItems().begin(); iter != list->getItems().end(); iter++)
|
||||
{
|
||||
auto item = dynamic_cast<CHeroItem*>(*iter);
|
||||
if (item && item->hero == hero)
|
||||
if (item && item->hero == hero && vstd::contains(LOCPLINT->wanderingHeroes, hero))
|
||||
{
|
||||
item->update();
|
||||
return;
|
||||
@ -817,13 +817,13 @@ void CInfoBar::showSelection()
|
||||
auto hero = dynamic_cast<const CGHeroInstance *>(adventureInt->selection);
|
||||
if (hero)
|
||||
{
|
||||
showHeroSelection(hero, false);
|
||||
showHeroSelection(hero);
|
||||
return;
|
||||
}
|
||||
auto town = dynamic_cast<const CGTownInstance *>(adventureInt->selection);
|
||||
if (town)
|
||||
{
|
||||
showTownSelection(town, false);
|
||||
showTownSelection(town);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@ -903,7 +903,7 @@ void CInfoBar::updateEnemyTurn(double progress)
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::showHeroSelection(const CGHeroInstance * hero, bool onlyUpdate)
|
||||
void CInfoBar::showHeroSelection(const CGHeroInstance * hero)
|
||||
{
|
||||
if (!hero)
|
||||
return;
|
||||
@ -914,7 +914,7 @@ void CInfoBar::showHeroSelection(const CGHeroInstance * hero, bool onlyUpdate)
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CInfoBar::showTownSelection(const CGTownInstance * town, bool onlyUpdate)
|
||||
void CInfoBar::showTownSelection(const CGTownInstance * town)
|
||||
{
|
||||
if (!town)
|
||||
return;
|
||||
|
@ -277,8 +277,6 @@ class CInfoBar : public CIntObject
|
||||
|
||||
//removes all information about current state, deactivates timer (if any)
|
||||
void reset(EState newState);
|
||||
//reset to default view - selected object
|
||||
void showSelection();
|
||||
|
||||
void tick();
|
||||
|
||||
@ -301,10 +299,12 @@ public:
|
||||
/// NOTE: currently DISABLED. Check comments in CInfoBar::CVisibleInfo::loadEnemyTurn()
|
||||
void updateEnemyTurn(double progress);
|
||||
|
||||
/// reset to default view - selected object
|
||||
void showSelection();
|
||||
|
||||
/// show hero\town information
|
||||
/// if onlyUpdate set to true this call won't switch to town\hero but only update current view
|
||||
void showHeroSelection(const CGHeroInstance * hero, bool onlyUpdate);
|
||||
void showTownSelection(const CGTownInstance * town, bool onlyUpdate);
|
||||
void showHeroSelection(const CGHeroInstance * hero);
|
||||
void showTownSelection(const CGTownInstance * town);
|
||||
|
||||
/// for 3 seconds shows amount of town halls and players status
|
||||
void showGameStatus();
|
||||
|
@ -981,7 +981,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
|
||||
assert(sel);
|
||||
LOCPLINT->cb->setSelection(sel);
|
||||
selection = sel;
|
||||
if (LOCPLINT->battleInt == NULL)
|
||||
if (LOCPLINT->battleInt == NULL && active & GENERAL)
|
||||
CCS->musich->playMusic(CCS->musich->terrainMusics[LOCPLINT->cb->getTile(sel->visitablePos())->tertype], -1);
|
||||
if(centerView)
|
||||
centerOn(sel);
|
||||
@ -991,7 +991,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
|
||||
{
|
||||
auto town = dynamic_cast<const CGTownInstance*>(sel);
|
||||
|
||||
infoBar.showTownSelection(town, false);
|
||||
infoBar.showTownSelection(town);
|
||||
townList.select(town);
|
||||
heroList.select(nullptr);
|
||||
|
||||
@ -1002,7 +1002,7 @@ void CAdvMapInt::select(const CArmedInstance *sel, bool centerView /*= true*/)
|
||||
{
|
||||
auto hero = dynamic_cast<const CGHeroInstance*>(sel);
|
||||
|
||||
infoBar.showHeroSelection(hero, false);
|
||||
infoBar.showHeroSelection(hero);
|
||||
heroList.select(hero);
|
||||
townList.select(nullptr);
|
||||
|
||||
|
@ -198,7 +198,6 @@ class CCastleInterface : public CWindowObject, public CWindowWithGarrison
|
||||
CGStatusBar * statusbar;
|
||||
|
||||
CTownInfo *hall, *fort;
|
||||
CTownList * townlist;
|
||||
|
||||
CAdventureMapButton *exit;
|
||||
CAdventureMapButton *split;
|
||||
@ -206,6 +205,8 @@ class CCastleInterface : public CWindowObject, public CWindowWithGarrison
|
||||
std::vector<CCreaInfo*> creainfo;//small icons of creatures (bottom-left corner);
|
||||
|
||||
public:
|
||||
CTownList * townlist;
|
||||
|
||||
//TODO: remove - currently used only in dialog messages
|
||||
CDefEssential* bicons; //150x70 buildings imgs
|
||||
|
||||
@ -214,6 +215,7 @@ public:
|
||||
HeroSlots *heroes;
|
||||
CCastleBuildings *builds;
|
||||
|
||||
//from - previously selected castle (if any)
|
||||
CCastleInterface(const CGTownInstance * Town, const CGTownInstance * from = nullptr); //c-tor
|
||||
~CCastleInterface();
|
||||
|
||||
|
@ -251,6 +251,17 @@ int main(int argc, char** argv)
|
||||
const JsonNode& video = settings["video"];
|
||||
const JsonNode& res = video["screenRes"];
|
||||
|
||||
//something is really wrong...
|
||||
if (res["width"].Float() < 100 || res["height"].Float() < 100)
|
||||
{
|
||||
tlog0 << "Fatal error: failed to load settings!\n";
|
||||
tlog0 << "Possible reasons:\n";
|
||||
tlog0 << "\tCorrupted local configuration file at " << GVCMIDirs.UserPath << "/config/settings.json\n";
|
||||
tlog0 << "\tMissing or corrupted global configuration file at " << GameConstants::DATA_DIR << "/config/defaultSettings.json\n";
|
||||
tlog0 << "VCMI will now exit...\n";
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
setScreenRes(res["width"].Float(), res["height"].Float(), video["bitsPerPixel"].Float(), video["fullscreen"].Bool());
|
||||
|
||||
tlog0 <<"\tInitializing screen: "<<pomtime.getDiff() << std::endl;
|
||||
|
@ -367,12 +367,36 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
|
||||
void CPlayerInterface::heroKilled(const CGHeroInstance* hero)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
|
||||
const CArmedInstance *newSelection = nullptr;
|
||||
if (makingTurn)
|
||||
{
|
||||
//find new object for selection: either hero
|
||||
int next = adventureInt->getNextHeroIndex(vstd::find_pos(wanderingHeroes, hero));
|
||||
if (next >= 0)
|
||||
newSelection = wanderingHeroes[next];
|
||||
|
||||
//or town
|
||||
if (!newSelection || newSelection == hero)
|
||||
{
|
||||
if (towns.empty())
|
||||
newSelection = nullptr;
|
||||
else
|
||||
newSelection = towns.front();
|
||||
}
|
||||
}
|
||||
|
||||
wanderingHeroes -= hero;
|
||||
if(vstd::contains(paths, hero))
|
||||
paths.erase(hero);
|
||||
|
||||
adventureInt->heroList.update(hero);
|
||||
if (makingTurn)
|
||||
adventureInt->select(newSelection, true);
|
||||
else
|
||||
adventureInt->selection = nullptr;
|
||||
}
|
||||
|
||||
void CPlayerInterface::heroCreated(const CGHeroInstance * hero)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
@ -560,6 +584,7 @@ void CPlayerInterface::buildChanged(const CGTownInstance *town, int buildingID,
|
||||
break;
|
||||
}
|
||||
adventureInt->townList.update(town);
|
||||
castleInt->townlist->update(town);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side)
|
||||
@ -1076,8 +1101,8 @@ void CPlayerInterface::availableCreaturesChanged( const CGDwelling *town )
|
||||
else if(GH.listInt.size() && (town->ID == 17 || town->ID == 20 || town->ID == 106)) //external dwelling
|
||||
{
|
||||
CRecruitmentWindow *crw = dynamic_cast<CRecruitmentWindow*>(GH.topInt());
|
||||
if(crw)
|
||||
crw->initCres();
|
||||
if(crw && crw->dwelling == town)
|
||||
crw->availableCreaturesChanged();
|
||||
}
|
||||
}
|
||||
|
||||
@ -2159,10 +2184,7 @@ void CPlayerInterface::tryDiggging(const CGHeroInstance *h)
|
||||
|
||||
void CPlayerInterface::updateInfo(const CGObjectInstance * specific)
|
||||
{
|
||||
if (specific->ID == GameConstants::TOWNI_TYPE)
|
||||
adventureInt->infoBar.showTownSelection(dynamic_cast<const CGTownInstance *>(specific), true);
|
||||
else
|
||||
adventureInt->infoBar.showHeroSelection(dynamic_cast<const CGHeroInstance *>(specific), true);
|
||||
adventureInt->infoBar.showSelection();
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleNewRoundFirst( int round )
|
||||
|
@ -1039,15 +1039,146 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool An
|
||||
anim = new CCreatureAnim(0, 0, cre->animDefName, Rect());
|
||||
anim->clipRect(cre->doubleWide?170:150, 155, bg->pos.w, bg->pos.h);
|
||||
anim->startPreview();
|
||||
|
||||
pos.w = bg->pos.w;
|
||||
pos.h = bg->pos.h;
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::Max()
|
||||
CRecruitmentWindow::CCreatureCard::CCreatureCard(CRecruitmentWindow *window, const CCreature *crea, int totalAmount):
|
||||
CIntObject(LCLICK | RCLICK),
|
||||
parent(window),
|
||||
selected(false),
|
||||
creature(crea),
|
||||
amount(totalAmount)
|
||||
{
|
||||
slider->moveToMax();
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
pic = new CCreaturePic(1,1, creature, true, true);
|
||||
// 1 + 1 px for borders
|
||||
pos.w = pic->pos.w + 2;
|
||||
pos.h = pic->pos.h + 2;
|
||||
}
|
||||
void CRecruitmentWindow::Buy()
|
||||
|
||||
void CRecruitmentWindow::CCreatureCard::select(bool on)
|
||||
{
|
||||
int crid = creatures[which].ID,
|
||||
selected = on;
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::CCreatureCard::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
if (down)
|
||||
parent->select(this);
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::CCreatureCard::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if (down)
|
||||
GH.pushInt(createCreWindow(creature->idNumber, 0, 0));
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to)
|
||||
{
|
||||
CIntObject::showAll(to);
|
||||
if (selected)
|
||||
drawBorder(to, pos, int3(248, 0, 0));
|
||||
else
|
||||
drawBorder(to, pos, int3(232, 212, 120));
|
||||
}
|
||||
|
||||
CRecruitmentWindow::CCostBox::CCostBox(Rect position, std::string title)
|
||||
{
|
||||
type |= REDRAW_PARENT;
|
||||
pos = position + pos;
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CLabel(pos.w/2, 10, FONT_SMALL, CENTER, Colors::Cornsilk, title);
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::CCostBox::set(TResources res)
|
||||
{
|
||||
//just update values
|
||||
BOOST_FOREACH(auto & item, resources)
|
||||
{
|
||||
item.second.first->setTxt(boost::lexical_cast<std::string>(res[item.first]));
|
||||
}
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::CCostBox::createItems(TResources res)
|
||||
{
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
BOOST_FOREACH(auto & curr, resources)
|
||||
{
|
||||
delete curr.second.first;
|
||||
delete curr.second.second;
|
||||
}
|
||||
resources.clear();
|
||||
|
||||
TResources::nziterator iter(res);
|
||||
while (iter.valid())
|
||||
{
|
||||
CAnimImage * image = new CAnimImage("RESOURCE", iter->resType);
|
||||
CLabel * text = new CLabel(15, 43, FONT_SMALL, CENTER, Colors::Cornsilk, "0");
|
||||
|
||||
resources.insert(std::make_pair(iter->resType, std::make_pair(text, image)));
|
||||
iter++;
|
||||
}
|
||||
|
||||
if (!resources.empty())
|
||||
{
|
||||
int curx = pos.w / 2 - (16 * resources.size()) - (8 * (resources.size() - 1));
|
||||
//reverse to display gold as first resource
|
||||
BOOST_REVERSE_FOREACH(auto & res, resources)
|
||||
{
|
||||
res.second.first->moveBy(Point(curx, 22));
|
||||
res.second.second->moveBy(Point(curx, 22));
|
||||
curx += 48;
|
||||
}
|
||||
}
|
||||
redraw();
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::select(CCreatureCard *card)
|
||||
{
|
||||
if (card == selected)
|
||||
return;
|
||||
|
||||
if (selected)
|
||||
selected->select(false);
|
||||
|
||||
selected = card;
|
||||
|
||||
if (selected)
|
||||
selected->select(true);
|
||||
|
||||
if (card)
|
||||
{
|
||||
si32 maxAmount = card->creature->maxAmount(LOCPLINT->cb->getResourceAmount());
|
||||
|
||||
vstd::amin(maxAmount, card->amount);
|
||||
|
||||
slider->setAmount(maxAmount);
|
||||
|
||||
if(slider->value)
|
||||
slider->moveTo(0);
|
||||
else // if slider already at 0 - emulate call to sliderMoved()
|
||||
sliderMoved(0);
|
||||
|
||||
costPerTroopValue->createItems(card->creature->cost);
|
||||
totalCostValue->createItems(card->creature->cost);
|
||||
|
||||
costPerTroopValue->set(card->creature->cost);
|
||||
|
||||
//Recruit %s
|
||||
title->setTxt(boost::str(boost::format(CGI->generaltexth->tcommands[21]) % card->creature->namePl));
|
||||
|
||||
maxButton->block(maxAmount == 0);
|
||||
slider->block(maxAmount == 0);
|
||||
}
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::buy()
|
||||
{
|
||||
int crid = selected->creature->idNumber,
|
||||
dstslot = dst-> getSlotFor(crid);
|
||||
|
||||
if(dstslot < 0 && !vstd::contains(CGI->arth->bigArtifacts,CGI->arth->convertMachineID(crid, true))) //no available slot
|
||||
@ -1067,175 +1198,122 @@ void CRecruitmentWindow::Buy()
|
||||
return;
|
||||
}
|
||||
|
||||
recruit(crid, slider->value);
|
||||
onRecruit(crid, slider->value);
|
||||
if(level >= 0)
|
||||
close();
|
||||
else
|
||||
slider->moveTo(0);
|
||||
|
||||
}
|
||||
void CRecruitmentWindow::Cancel()
|
||||
{
|
||||
close();
|
||||
}
|
||||
void CRecruitmentWindow::sliderMoved(int to)
|
||||
{
|
||||
buy->block(!to);
|
||||
redraw();
|
||||
}
|
||||
void CRecruitmentWindow::clickLeft(tribool down, bool previousState)
|
||||
{
|
||||
for(int i=0;i<creatures.size();i++)
|
||||
{
|
||||
Rect creaPos = Rect(creatures[i].pos) + pos;
|
||||
if(isItIn(&creaPos, GH.current->motion.x, GH.current->motion.y))
|
||||
{
|
||||
which = i;
|
||||
int newAmount = std::min(amounts[i],creatures[i].amount);
|
||||
slider->setAmount(newAmount);
|
||||
max->block(!newAmount);
|
||||
|
||||
if(slider->value > newAmount)
|
||||
slider->moveTo(newAmount);
|
||||
else
|
||||
slider->moveTo(slider->value);
|
||||
redraw();
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
void CRecruitmentWindow::clickRight(tribool down, bool previousState)
|
||||
{
|
||||
if(down)
|
||||
{
|
||||
int curx = 192 + 51 - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
|
||||
for(int i=0;i<creatures.size();i++)
|
||||
{
|
||||
const int sCREATURE_WIDTH = CREATURE_WIDTH; // gcc -O0 workaround
|
||||
Rect creatureRect = genRect(132, sCREATURE_WIDTH, pos.x+curx, pos.y+64);
|
||||
if(isItIn(&creatureRect, GH.current->motion.x, GH.current->motion.y))
|
||||
{
|
||||
CIntObject *popup = createCreWindow(creatures[i].ID, 0, 0);
|
||||
GH.pushInt(popup);
|
||||
break;
|
||||
}
|
||||
curx += TOTAL_CREATURE_WIDTH;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::showAll(SDL_Surface * to)
|
||||
{
|
||||
CWindowObject::showAll(to);
|
||||
|
||||
// recruit\total values
|
||||
drawBorder(to, pos.x + 172, pos.y + 222, 67, 42, int3(239,215,123));
|
||||
drawBorder(to, pos.x + 246, pos.y + 222, 67, 42, int3(239,215,123));
|
||||
|
||||
//cost boxes
|
||||
drawBorder(to, pos.x + 64, pos.y + 222, 99, 76, int3(239,215,123));
|
||||
drawBorder(to, pos.x + 322, pos.y + 222, 99, 76, int3(239,215,123));
|
||||
|
||||
//buttons borders
|
||||
drawBorder(to, pos.x + 133, pos.y + 312, 66, 34, int3(173,142,66));
|
||||
drawBorder(to, pos.x + 211, pos.y + 312, 66, 34, int3(173,142,66));
|
||||
drawBorder(to, pos.x + 289, pos.y + 312, 66, 34, int3(173,142,66));
|
||||
|
||||
char pom[15];
|
||||
SDL_itoa(creatures[which].amount-slider->value,pom,10); //available
|
||||
printAtMiddleLoc(pom,205,253,FONT_SMALL,Colors::Cornsilk,to);
|
||||
SDL_itoa(slider->value,pom,10); //recruit
|
||||
printAtMiddleLoc(pom,279,253,FONT_SMALL,Colors::Cornsilk,to);
|
||||
printAtMiddleLoc(CGI->generaltexth->allTexts[16] + " " + CGI->creh->creatures[creatures[which].ID]->namePl,243,32,FONT_BIG,Colors::Jasmine,to); //eg "Recruit Dragon flies"
|
||||
|
||||
int curx = 122-creatures[which].res.size()*24;
|
||||
for(int i=creatures[which].res.size()-1; i>=0; i--)// decrement used to make gold displayed as first res
|
||||
{
|
||||
blitAtLoc(graphics->resources32->ourImages[creatures[which].res[i].first].bitmap,curx,243,to);
|
||||
blitAtLoc(graphics->resources32->ourImages[creatures[which].res[i].first].bitmap,curx+258,243,to);
|
||||
SDL_itoa(creatures[which].res[i].second,pom,10);
|
||||
printAtMiddleLoc(pom,curx+15,287,FONT_SMALL,Colors::Cornsilk,to);
|
||||
SDL_itoa(creatures[which].res[i].second * slider->value,pom,10);
|
||||
printAtMiddleLoc(pom,curx+15+258,287,FONT_SMALL,Colors::Cornsilk,to);
|
||||
curx+=32+16;//size of bitmap + distance between them
|
||||
}
|
||||
|
||||
for(int j=0;j<creatures.size();j++)
|
||||
{
|
||||
if(which==j)
|
||||
drawBorderLoc(to,creatures[j].pos,int3(255,0,0));
|
||||
else
|
||||
drawBorderLoc(to,creatures[j].pos,int3(239,215,123));
|
||||
}
|
||||
}
|
||||
|
||||
CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const boost::function<void(int,int)> &Recruit, int y_offset):
|
||||
CWindowObject(PLAYER_COLORED, "TPRCRT"),
|
||||
recruit(Recruit),
|
||||
dwelling(Dwelling),
|
||||
onRecruit(Recruit),
|
||||
level(Level),
|
||||
dst(Dst)
|
||||
dst(Dst),
|
||||
selected(nullptr),
|
||||
dwelling(Dwelling)
|
||||
{
|
||||
addUsedEvents(LCLICK | RCLICK);
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
moveBy(Point(0, y_offset));
|
||||
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
||||
|
||||
which = 0;
|
||||
bar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
||||
max = new CAdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CRecruitmentWindow::Max,this),134,313,"IRCBTNS.DEF",SDLK_m);
|
||||
buy = new CAdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecruitmentWindow::Buy,this),212,313,"IBY6432.DEF",SDLK_RETURN);
|
||||
cancel = new CAdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecruitmentWindow::Cancel,this),290,313,"ICN6432.DEF",SDLK_ESCAPE);
|
||||
slider = new CSlider(176,279,135,0,0,0,0,true);
|
||||
slider->moved = boost::bind(&CRecruitmentWindow::sliderMoved,this, _1);
|
||||
|
||||
initCres();
|
||||
maxButton = new CAdventureMapButton(CGI->generaltexth->zelp[553],boost::bind(&CSlider::moveToMax,slider),134,313,"IRCBTNS.DEF",SDLK_m);
|
||||
buyButton = new CAdventureMapButton(CGI->generaltexth->zelp[554],boost::bind(&CRecruitmentWindow::buy,this),212,313,"IBY6432.DEF",SDLK_RETURN);
|
||||
cancelButton = new CAdventureMapButton(CGI->generaltexth->zelp[555],boost::bind(&CRecruitmentWindow::close,this),290,313,"ICN6432.DEF",SDLK_ESCAPE);
|
||||
|
||||
title = new CLabel(243, 32, FONT_BIG, CENTER, Colors::Jasmine);
|
||||
availableValue = new CLabel(205, 253, FONT_SMALL, CENTER, Colors::Cornsilk);
|
||||
toRecruitValue = new CLabel(279, 253, FONT_SMALL, CENTER, Colors::Cornsilk);
|
||||
|
||||
costPerTroopValue = new CCostBox(Rect(65, 222, 97, 74), CGI->generaltexth->allTexts[346]);
|
||||
totalCostValue = new CCostBox(Rect(323, 222, 97, 74), CGI->generaltexth->allTexts[466]);
|
||||
|
||||
new CLabel(113, 232, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[346]); //cost per troop t
|
||||
new CLabel(205, 233, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[465]); //available t
|
||||
new CLabel(279, 233, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[16]); //recruit t
|
||||
new CLabel(371, 232, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[466]); //total cost t
|
||||
|
||||
//border for creatures
|
||||
int curx = 192 + 50 - (CREATURE_WIDTH*creatures.size()/2) - (SPACE_BETWEEN*(creatures.size()-1)/2);
|
||||
for(int i=0;i<creatures.size();i++)
|
||||
{
|
||||
creatures[i].pos.x = curx-1;
|
||||
creatures[i].pos.y = 65 - 1;
|
||||
creatures[i].pos.w = 100 + 2;
|
||||
creatures[i].pos.h = 130 + 2;
|
||||
|
||||
creatures[i].pic = new CCreaturePic(curx, 65, CGI->creh->creatures[creatures[i].ID]);
|
||||
curx += TOTAL_CREATURE_WIDTH;
|
||||
}
|
||||
|
||||
if(!creatures[0].amount || !amounts[0])
|
||||
{
|
||||
max->block(true);
|
||||
slider->block(true);
|
||||
}
|
||||
buy->block(true);
|
||||
availableCreaturesChanged();
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::initCres()
|
||||
void CRecruitmentWindow::availableCreaturesChanged()
|
||||
{
|
||||
creatures.clear();
|
||||
amounts.clear();
|
||||
OBJ_CONSTRUCTION_CAPTURING_ALL;
|
||||
|
||||
//deselect card
|
||||
select(nullptr);
|
||||
|
||||
static const int SPACE_BETWEEN = 18;
|
||||
static const int CREATURE_WIDTH = 102;
|
||||
static const int TOTAL_CREATURE_WIDTH = SPACE_BETWEEN + CREATURE_WIDTH;
|
||||
|
||||
//delete old cards
|
||||
BOOST_FOREACH(auto & card, cards)
|
||||
delete card;
|
||||
cards.clear();
|
||||
|
||||
for(int i=0; i<dwelling->creatures.size(); i++)
|
||||
{
|
||||
//find appropriate level
|
||||
if(level >= 0 && i != level)
|
||||
continue;
|
||||
|
||||
for(int j = dwelling->creatures[i].second.size() - 1; j >= 0 ; j--)
|
||||
{
|
||||
creatures.resize(creatures.size()+1);
|
||||
creinfo &cur = creatures.back();
|
||||
int amount = dwelling->creatures[i].first;
|
||||
|
||||
cur.amount = dwelling->creatures[i].first;
|
||||
cur.ID = dwelling->creatures[i].second[j];
|
||||
const CCreature * cre= CGI->creh->creatures[cur.ID];
|
||||
|
||||
for(int k=0; k<cre->cost.size(); k++)
|
||||
if(cre->cost[k])
|
||||
cur.res.push_back(std::make_pair(k,cre->cost[k]));
|
||||
amounts.push_back(cre->maxAmount(LOCPLINT->cb->getResourceAmount()));
|
||||
}
|
||||
//create new cards
|
||||
BOOST_REVERSE_FOREACH(auto & creature, dwelling->creatures[i].second)
|
||||
cards.push_back(new CCreatureCard(this, CGI->creh->creatures[creature], amount));
|
||||
}
|
||||
|
||||
slider->setAmount(std::min(amounts[which],creatures[which].amount));
|
||||
assert(!cards.empty());
|
||||
|
||||
//now we know total amount of cards and can move them to correct position
|
||||
int curx = 192 + 50 - (CREATURE_WIDTH*cards.size()/2) - (SPACE_BETWEEN*(cards.size()-1)/2);
|
||||
BOOST_FOREACH(auto & card, cards)
|
||||
{
|
||||
card->moveBy(Point(curx, 64));
|
||||
curx += TOTAL_CREATURE_WIDTH;
|
||||
}
|
||||
|
||||
select(cards.front());
|
||||
|
||||
if(slider->value)
|
||||
slider->moveTo(0);
|
||||
else // if slider already at 0 - emulate call to sliderMoved()
|
||||
sliderMoved(0);
|
||||
}
|
||||
|
||||
void CRecruitmentWindow::sliderMoved(int to)
|
||||
{
|
||||
if (!selected)
|
||||
return;
|
||||
|
||||
buyButton->block(!to);
|
||||
availableValue->setTxt(boost::lexical_cast<std::string>(selected->amount - to));
|
||||
toRecruitValue->setTxt(boost::lexical_cast<std::string>(to));
|
||||
|
||||
totalCostValue->set(selected->creature->cost * to);
|
||||
}
|
||||
|
||||
CSplitWindow::CSplitWindow(const CCreature * creature, boost::function<void(int, int)> callback_,
|
||||
@ -2202,6 +2280,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket *Market, const CGHeroInstan
|
||||
case EMarketMode::RESOURCE_PLAYER:
|
||||
case EMarketMode::RESOURCE_ARTIFACT:
|
||||
new CLabel(154, 148, FONT_SMALL, CENTER, Colors::Cornsilk, CGI->generaltexth->allTexts[270]);
|
||||
break;
|
||||
|
||||
case EMarketMode::CREATURE_RESOURCE:
|
||||
//%s's Creatures
|
||||
@ -3138,6 +3217,9 @@ void CSystemOptionsWindow::setGameRes(int index)
|
||||
while (index--)
|
||||
iter++;
|
||||
|
||||
//do not set resolution to illegal one (0x0)
|
||||
assert(iter!=conf.guiOptions.end() && iter->first.first > 0 && iter->first.second > 0);
|
||||
|
||||
Settings gameRes = settings.write["video"]["screenRes"];
|
||||
gameRes["width"].Float() = iter->first.first;
|
||||
gameRes["height"].Float() = iter->first.second;
|
||||
|
@ -333,39 +333,62 @@ public:
|
||||
/// Recruitment window where you can recruit creatures
|
||||
class CRecruitmentWindow : public CWindowObject
|
||||
{
|
||||
public:
|
||||
static const int SPACE_BETWEEN = 18;
|
||||
static const int CREATURE_WIDTH = 102;
|
||||
static const int TOTAL_CREATURE_WIDTH = SPACE_BETWEEN + CREATURE_WIDTH;
|
||||
|
||||
struct creinfo
|
||||
class CCreatureCard : public CIntObject
|
||||
{
|
||||
SDL_Rect pos;
|
||||
CRecruitmentWindow * parent;
|
||||
CCreaturePic *pic; //creature's animation
|
||||
int ID, amount; //creature ID and available amount
|
||||
std::vector<std::pair<int,int> > res; //res_id - cost_per_unit
|
||||
};
|
||||
std::vector<int> amounts; //how many creatures we can afford
|
||||
std::vector<creinfo> creatures; //recruitable creatures
|
||||
boost::function<void(int,int)> recruit; //void (int ID, int amount) <-- call to recruit creatures
|
||||
CSlider *slider; //for selecting amount
|
||||
CAdventureMapButton *max, *buy, *cancel;
|
||||
CGStatusBar *bar;
|
||||
int which; //which creature is active
|
||||
bool selected;
|
||||
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void showAll(SDL_Surface *to);
|
||||
public:
|
||||
const CCreature * creature;
|
||||
si32 amount;
|
||||
|
||||
void select(bool on);
|
||||
|
||||
CCreatureCard(CRecruitmentWindow * window, const CCreature *crea, int totalAmount);
|
||||
};
|
||||
|
||||
/// small class to display creature costs
|
||||
class CCostBox : public CIntObject
|
||||
{
|
||||
std::map<int, std::pair<CLabel *, CAnimImage * > > resources;
|
||||
public:
|
||||
//res - resources to show
|
||||
void set(TResources res);
|
||||
//res - visible resources
|
||||
CCostBox(Rect position, std::string title);
|
||||
void createItems(TResources res);
|
||||
};
|
||||
|
||||
boost::function<void(int,int)> onRecruit; //void (int ID, int amount) <-- call to recruit creatures
|
||||
|
||||
const CGDwelling *dwelling;
|
||||
int level;
|
||||
const CArmedInstance *dst;
|
||||
|
||||
void Max();
|
||||
void Buy();
|
||||
void Cancel();
|
||||
CCreatureCard * selected;
|
||||
std::vector<CCreatureCard *> cards;
|
||||
|
||||
CSlider *slider; //for selecting amount
|
||||
CAdventureMapButton *maxButton, *buyButton, *cancelButton;
|
||||
//labels for visible values
|
||||
CLabel * title;
|
||||
CLabel * availableValue;
|
||||
CLabel * toRecruitValue;
|
||||
CCostBox * costPerTroopValue;
|
||||
CCostBox * totalCostValue;
|
||||
|
||||
void select(CCreatureCard * card);
|
||||
void buy();
|
||||
void sliderMoved(int to);
|
||||
void clickLeft(tribool down, bool previousState);
|
||||
void clickRight(tribool down, bool previousState);
|
||||
void showAll(SDL_Surface * to);
|
||||
void initCres();
|
||||
|
||||
void showAll(SDL_Surface *to);
|
||||
public:
|
||||
const CGDwelling * const dwelling;
|
||||
CRecruitmentWindow(const CGDwelling *Dwelling, int Level, const CArmedInstance *Dst, const boost::function<void(int,int)> & Recruit, int y_offset = 0); //creatures - pairs<creature_ID,amount> //c-tor
|
||||
void availableCreaturesChanged();
|
||||
};
|
||||
|
||||
/// Split window where creatures can be splitted up into two single unit stacks
|
||||
|
@ -751,17 +751,22 @@ CSlider::CSlider(int x, int y, int totalw, boost::function<void(int)> Moved, int
|
||||
if(style == 0)
|
||||
{
|
||||
std::string name = horizontal?"IGPCRDIV.DEF":"OVBUTN2.DEF";
|
||||
CAnimation *animLeft = new CAnimation(name);
|
||||
//NOTE: this images do not have "blocked" frames. They should be implemented somehow (e.g. palette transform or something...)
|
||||
|
||||
//use source def to create custom animations. Format "name.def:123" will load this frame from def file
|
||||
CAnimation *animLeft = new CAnimation();
|
||||
animLeft->setCustom(name + ":0", 0);
|
||||
animLeft->setCustom(name + ":1", 1);
|
||||
left->setImage(animLeft);
|
||||
left->setOffset(0);
|
||||
|
||||
CAnimation *animRight = new CAnimation(name);
|
||||
CAnimation *animRight = new CAnimation();
|
||||
animRight->setCustom(name + ":2", 0);
|
||||
animRight->setCustom(name + ":3", 1);
|
||||
right->setImage(animRight);
|
||||
right->setOffset(2);
|
||||
|
||||
CAnimation *animSlider = new CAnimation(name);
|
||||
CAnimation *animSlider = new CAnimation();
|
||||
animSlider->setCustom(name + ":4", 0);
|
||||
slider->setImage(animSlider);
|
||||
slider->setOffset(4);
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1512,7 +1517,7 @@ bool CTextInput::captureThisEvent(const SDL_KeyboardEvent & key)
|
||||
|
||||
void CTextInput::filenameFilter(std::string & text, const std::string &)
|
||||
{
|
||||
static const std::string forbiddenChars = "<>:\"/\\|?*"; //if we are entering a filename, some special characters won't be allowed
|
||||
static const std::string forbiddenChars = "<>:\"/\\|?*\r\n"; //if we are entering a filename, some special characters won't be allowed
|
||||
size_t pos;
|
||||
while ((pos = text.find_first_of(forbiddenChars)) != std::string::npos)
|
||||
text.erase(pos, 1);
|
||||
|
@ -995,7 +995,7 @@ int CGameInfoCallback::canBuildStructure( const CGTownInstance *t, int ID )
|
||||
}
|
||||
else if(ID == 6) //shipyard
|
||||
{
|
||||
const TerrainTile *tile = getTile(t->bestLocation());
|
||||
const TerrainTile *tile = getTile(t->bestLocation(), false);
|
||||
|
||||
if(!tile || tile->tertype != TerrainTile::water )
|
||||
ret = EBuildingState::NO_WATER; //lack of water
|
||||
|
Loading…
Reference in New Issue
Block a user