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

Quick Army Purhase in Town Screen

Mouse click on castle icon (it is now clickable) - quick recruit of all
available creatures.
This commit is contained in:
FeniksFire 2017-11-01 14:58:49 +01:00
parent 86021f0bda
commit a4f701014b
11 changed files with 439 additions and 70 deletions

View File

@ -32,6 +32,7 @@ set(client_SRCS
windows/CAdvmapInterface.cpp
windows/CCastleInterface.cpp
windows/CCreatureWindow.cpp
windows/CreaturePurhaseCard.cpp
windows/CHeroWindow.cpp
windows/CKingdomInterface.cpp
windows/CQuestLog.cpp
@ -40,8 +41,10 @@ set(client_SRCS
windows/CWindowObject.cpp
windows/GUIClasses.cpp
windows/InfoWindows.cpp
windows/QuickRecruitmentWindow.cpp
CBitmapHandler.cpp
CreatureCostBox.cpp
CDefHandler.cpp
CGameInfo.cpp
Client.cpp
@ -87,6 +90,7 @@ set(client_HEADERS
windows/CAdvmapInterface.h
windows/CCastleInterface.h
windows/CCreatureWindow.h
windows/CreaturePurhaseCard.h
windows/CHeroWindow.h
windows/CKingdomInterface.h
windows/CQuestLog.h
@ -95,8 +99,10 @@ set(client_HEADERS
windows/CWindowObject.h
windows/GUIClasses.h
windows/InfoWindows.h
windows/QuickRecruitmentWindow.h
CBitmapHandler.h
CreatureCostBox.h
CDefHandler.h
CGameInfo.h
Client.h

View File

@ -0,0 +1,63 @@
/*
* CreatureCostBox.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "CreatureCostBox.h"
#include "windows/CAdvmapInterface.h"
#include "gui/CGuiHandler.h"
void CreatureCostBox::set(TResources res)
{
for(auto & item : resources)
item.second.first->setText(boost::lexical_cast<std::string>(res[item.first]));
}
CreatureCostBox::CreatureCostBox(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::WHITE, title);
}
void CreatureCostBox::createItems(TResources res)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
for(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::WHITE, "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
for (auto & res : boost::adaptors::reverse(resources))
{
res.second.first->moveBy(Point(curx, 22));
res.second.second->moveBy(Point(curx, 22));
curx += 48;
}
}
redraw();
}

22
client/CreatureCostBox.h Normal file
View File

@ -0,0 +1,22 @@
/*
* CreatureCostBox.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "widgets/Images.h"
#include "../lib/ResourceSet.h"
class CreatureCostBox : public CIntObject
{
std::map<int, std::pair<CLabel *, CAnimImage * > > resources;
public:
void set(TResources res);
CreatureCostBox(Rect position, std::string title);
void createItems(TResources res);
};

View File

@ -14,6 +14,7 @@
#include "CHeroWindow.h"
#include "CTradeWindow.h"
#include "GUIClasses.h"
#include "QuickRecruitmentWindow.h"
#include "../CBitmapHandler.h"
#include "../CGameInfo.h"
@ -21,7 +22,6 @@
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../Graphics.h"
#include "../gui/CGuiHandler.h"
#include "../gui/SDL_Extensions.h"
#include "../windows/InfoWindows.h"
@ -795,6 +795,11 @@ void CCastleBuildings::enterDwelling(int level)
GH.pushInt(new CRecruitmentWindow(town, level, town, recruitCb, -87));
}
void CCastleBuildings::enterToTheQuickRecruitmentWindow()
{
GH.pushInt(new QuickRecruitmentWindow(town));
}
void CCastleBuildings::enterFountain(BuildingID building)
{
std::vector<CComponent*> comps(1, new CComponent(CComponent::building,town->subID,building));
@ -885,6 +890,7 @@ CCastleInterface::CCastleInterface(const CGTownInstance * Town, const CGTownInst
town(Town)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
LOCPLINT->castleInt = this;
addUsedEvents(KEYBOARD);
@ -990,7 +996,8 @@ void CCastleInterface::recreateIcons()
hall = new CTownInfo( 80, 413, town, true);
fort = new CTownInfo(122, 413, town, false);
fastArmyPurhase = std::make_shared<CButton>(Point(122, 413), "itmcl.def", CButton::tooltip("quick army purhase"), [&](){builds->enterToTheQuickRecruitmentWindow();});
fastArmyPurhase->setImageOrder(town->fortLevel()-1,town->fortLevel()-1,town->fortLevel()-1,town->fortLevel()-1);
for (auto & elem : creainfo)
delete elem;
creainfo.clear();

View File

@ -143,6 +143,7 @@ public:
~CCastleBuildings();
void enterDwelling(int level);
void enterToTheQuickRecruitmentWindow();
void buildingClicked(BuildingID building);
void addBuilding(BuildingID building);
@ -180,8 +181,8 @@ class CTownInfo : public CIntObject
{
const CGTownInstance *town;
const CBuilding *building;
CAnimImage *picture;
public:
CAnimImage * picture;
//if (townHall) hall-capital else fort - castle
CTownInfo(int posX, int posY, const CGTownInstance* town, bool townHall);
@ -204,6 +205,7 @@ class CCastleInterface : public CWindowObject, public CWindowWithGarrison
CButton *exit;
CButton *split;
std::shared_ptr<CButton> fastArmyPurhase;
std::vector<CCreaInfo*> creainfo;//small icons of creatures (bottom-left corner);

View File

@ -0,0 +1,80 @@
/*
* CreaturePurhaseCard.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "CreaturePurhaseCard.h"
#include "CAdvmapInterface.h"
#include "CHeroWindow.h"
#include "../widgets/Buttons.h"
#include "../../CCallback.h"
#include "../CreatureCostBox.h"
#include "QuickRecruitmentWindow.h"
void CreaturePurhaseCard::initButtons()
{
initMaxButton();
initMinButton();
}
void CreaturePurhaseCard::initMaxButton()
{
maxButton = std::make_shared<CButton>(Point(pos.x + 52, pos.y + 178), "iam014.def", CButton::tooltip(), std::bind(&CSlider::moveToMax,slider), SDLK_m);
}
void CreaturePurhaseCard::initMinButton()
{
minButton = std::make_shared<CButton>(Point(pos.x, pos.y + 178), "iam015.def", CButton::tooltip(), std::bind(&CSlider::moveToMin,slider), SDLK_m);
}
void CreaturePurhaseCard::initAmountInfo()
{
availableAmount = std::make_shared<CLabel>(pos.x + 27, pos.y + 146, FONT_SMALL, CENTER, Colors::YELLOW);
purhaseAmount = std::make_shared<CLabel>(pos.x + 77, pos.y + 146, FONT_SMALL, CENTER, Colors::WHITE);
updateAmountInfo(0);
}
void CreaturePurhaseCard::updateAmountInfo(int value)
{
availableAmount->setText(boost::lexical_cast<std::string>(maxamount-value));
purhaseAmount->setText(boost::lexical_cast<std::string>(value));
}
void CreaturePurhaseCard::initSlider()
{
slider = std::make_shared<CSlider>(Point(pos.x, pos.y + 158), 102, std::bind(&CreaturePurhaseCard::sliderMoved, this , _1), 0, maxamount, 0);
}
void CreaturePurhaseCard::initCostBox()
{
cost = std::make_shared<CreatureCostBox>(Rect(pos.x, pos.y + 194, 97, 74), "");
cost->createItems(creature->cost);
}
void CreaturePurhaseCard::sliderMoved(int to)
{
updateAmountInfo(to);
cost->set(creature->cost * to);
parent->updateAllSliders();
}
CreaturePurhaseCard::CreaturePurhaseCard(const CCreature * monster, Point p, int amount, QuickRecruitmentWindow * par) : creature(monster), parent(par), maxamount(amount)
{
moveTo(Point(p.x, p.y));
initView();
}
void CreaturePurhaseCard::initView()
{
picture = std::make_shared<CCreaturePic>(pos.x, pos.y, creature);
initAmountInfo();
initSlider();
initButtons();
initCostBox();
}

View File

@ -0,0 +1,49 @@
/*
* CreaturePurhaseCard.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../widgets/Images.h"
class CCreaturePic;
class CSlider;
class CButton;
class CreatureCostBox;
class QuickRecruitmentWindow;
class CreaturePurhaseCard : public CIntObject
{
public:
const CCreature * creature;
std::shared_ptr<CSlider> slider;
QuickRecruitmentWindow * parent;
int maxamount;
void sliderMoved(int to);
CreaturePurhaseCard(const CCreature * monster, Point p, int amount, QuickRecruitmentWindow * par);
private:
void initView();
void initButtons();
void initMaxButton();
void initMinButton();
void initAmountInfo();
void updateAmountInfo(int value);
void initSlider();
void initCostBox();
std::shared_ptr<CButton> maxButton, minButton;
std::shared_ptr<CLabel> availableAmount, purhaseAmount;
std::shared_ptr<CCreaturePic> picture;
std::shared_ptr<CreatureCostBox> cost;
};

View File

@ -14,6 +14,7 @@
#include "CCastleInterface.h"
#include "CCreatureWindow.h"
#include "CHeroWindow.h"
#include "CreatureCostBox.h"
#include "../CBitmapHandler.h"
#include "../CGameInfo.h"
@ -108,57 +109,6 @@ void CRecruitmentWindow::CCreatureCard::showAll(SDL_Surface * to)
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::WHITE, title);
}
void CRecruitmentWindow::CCostBox::set(TResources res)
{
//just update values
for(auto & item : resources)
{
item.second.first->setText(boost::lexical_cast<std::string>(res[item.first]));
}
}
void CRecruitmentWindow::CCostBox::createItems(TResources res)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
for(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::WHITE, "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
for (auto & res : boost::adaptors::reverse(resources))
{
res.second.first->moveBy(Point(curx, 22));
res.second.second->moveBy(Point(curx, 22));
curx += 48;
}
}
redraw();
}
void CRecruitmentWindow::select(CCreatureCard *card)
{
@ -268,8 +218,8 @@ CRecruitmentWindow::CRecruitmentWindow(const CGDwelling *Dwelling, int Level, co
availableValue = new CLabel(205, 253, FONT_SMALL, CENTER, Colors::WHITE);
toRecruitValue = new CLabel(279, 253, FONT_SMALL, CENTER, Colors::WHITE);
costPerTroopValue = new CCostBox(Rect(65, 222, 97, 74), CGI->generaltexth->allTexts[346]);
totalCostValue = new CCostBox(Rect(323, 222, 97, 74), CGI->generaltexth->allTexts[466]);
costPerTroopValue = new CreatureCostBox(Rect(65, 222, 97, 74), CGI->generaltexth->allTexts[346]);
totalCostValue = new CreatureCostBox(Rect(323, 222, 97, 74), CGI->generaltexth->allTexts[466]);
new CLabel(205, 233, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[465]); //available t
new CLabel(279, 233, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[16]); //recruit t

View File

@ -18,6 +18,7 @@
#include "../windows/CWindowObject.h"
class CGDwelling;
class CreatureCostBox;
class IMarket;
class CCreaturePic;
class MoraleLuckBox;
@ -54,18 +55,6 @@ class CRecruitmentWindow : public CWindowObject
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);
};
std::function<void(CreatureID,int)> onRecruit; //void (int ID, int amount) <-- call to recruit creatures
int level;
@ -80,8 +69,8 @@ class CRecruitmentWindow : public CWindowObject
CLabel * title;
CLabel * availableValue;
CLabel * toRecruitValue;
CCostBox * costPerTroopValue;
CCostBox * totalCostValue;
CreatureCostBox * costPerTroopValue;
CreatureCostBox * totalCostValue;
void select(CCreatureCard * card);
void buy();

View File

@ -0,0 +1,157 @@
/*
* QuickRecruitmentWindow.cpp, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#include "StdInc.h"
#include "QuickRecruitmentWindow.h"
#include "../../lib/mapObjects/CGTownInstance.h"
#include "../CPlayerInterface.h"
#include "../widgets/Buttons.h"
#include "../gui/CGuiHandler.h"
#include "../../CCallback.h"
#include "../CreatureCostBox.h"
#include "../lib/ResourceSet.h"
#include "CreaturePurhaseCard.h"
void QuickRecruitmentWindow::setButtons()
{
setCancelButton();
setBuyButton();
setMaxButton();
}
void QuickRecruitmentWindow::setCancelButton()
{
cancelButton = std::make_shared<CButton>(Point((pos.w / 2) + 47, 417), "ICN6432.DEF", CButton::tooltip(), [&](){ close(); }, SDLK_RETURN);
cancelButton->setImageOrder(0, 1, 2, 3);
}
void QuickRecruitmentWindow::setBuyButton()
{
buyButton = std::make_shared<CButton>(Point((pos.w/2)-33, 417), "IBY6432.DEF", CButton::tooltip(), [&](){ purhaseUnits(); });
cancelButton->assignedKeys.insert(SDLK_ESCAPE);
buyButton->setImageOrder(0, 1, 2, 3);
}
void QuickRecruitmentWindow::setMaxButton()
{
maxButton = std::make_shared<CButton>(Point((pos.w/2)-113, 417), "IRCBTNS.DEF", CButton::tooltip(), [&](){ maxAllCards(cards); });
maxButton->setImageOrder(0, 1, 2, 3);
}
void QuickRecruitmentWindow::setCreaturePurhaseCards()
{
Point pos = Point(8,64);
for (int i=0; i < GameConstants::CREATURES_PER_TOWN; i++)
{
if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first)
{
CreatureID crid = town->creatures[i].second[0];
if(town->creatures[i].second.size() > 1)
crid = town->creatures[i].second[1];
cards.push_back(std::make_shared<CreaturePurhaseCard>(VLC->creh->creatures[crid], pos, town->creatures[i].first, this));
pos.x += 108;
}
}
totalCost = std::make_shared<CreatureCostBox>(Rect((this->pos.w/2)-45, pos.y + 260, 97, 74), "");
}
void QuickRecruitmentWindow::initWindow()
{
pos.x = 238;
pos.y = 45;
pos.w = 332;
pos.h = 461;
int creaturesAmount = getAvailableCreatures();
if(creaturesAmount > 3)
{
pos.w += 108 * (creaturesAmount - 3);
pos.x -= 55 * (creaturesAmount - 3);
}
backgroundTexture = std::make_shared<CFilledTexture>("DIBOXBCK.pcx", Rect(0, 0, pos.w, pos.h));
}
void QuickRecruitmentWindow::maxAllCards(std::vector<std::shared_ptr<CreaturePurhaseCard> > cards)
{
auto allAvailableResources = LOCPLINT->cb->getResourceAmount();
for(auto i : boost::adaptors::reverse(cards))
{
si32 maxAmount = i->creature->maxAmount(allAvailableResources);
vstd::amin(maxAmount, i->maxamount);
i->slider->setAmount(maxAmount);
if(i->slider->getValue() != maxAmount)
i->slider->moveTo(maxAmount);
else
i->sliderMoved(maxAmount);
i->slider->moveToMax();
allAvailableResources -= (i->creature->cost * maxAmount);
}
maxButton->block(allAvailableResources == LOCPLINT->cb->getResourceAmount());
}
void QuickRecruitmentWindow::purhaseUnits()
{
for(auto selected : cards)
{
if(selected->slider->getValue())
{
auto onRecruit = [=](CreatureID id, int count){ LOCPLINT->cb->recruitCreatures(town, town->getUpperArmy(), id, count, selected->creature->level-1); };
CreatureID crid = selected->creature->idNumber;
SlotID dstslot = town -> getSlotFor(crid);
if(!dstslot.validSlot())
continue;
onRecruit(crid, selected->slider->getValue());
}
}
close();
}
int QuickRecruitmentWindow::getAvailableCreatures()
{
int creaturesAmount = 0;
for (int i=0; i< GameConstants::CREATURES_PER_TOWN; i++)
if(!town->town->creatures.at(i).empty() && !town->creatures.at(i).second.empty() && town->creatures[i].first)
creaturesAmount++;
return creaturesAmount;
}
void QuickRecruitmentWindow::updateAllSliders()
{
auto allAvailableResources = LOCPLINT->cb->getResourceAmount();
for(auto i : boost::adaptors::reverse(cards))
allAvailableResources -= (i->creature->cost * i->slider->getValue());
for(auto i : cards)
{
si32 maxAmount = i->creature->maxAmount(allAvailableResources);
vstd::amin(maxAmount, i->maxamount);
if(maxAmount < 0)
continue;
if(i->slider->getValue() + maxAmount < i->maxamount)
i->slider->setAmount(i->slider->getValue() + maxAmount);
else
i->slider->setAmount(i->maxamount);
i->slider->moveTo(i->slider->getValue());
}
totalCost->createItems(LOCPLINT->cb->getResourceAmount() - allAvailableResources);
totalCost->set(LOCPLINT->cb->getResourceAmount() - allAvailableResources);
}
QuickRecruitmentWindow::QuickRecruitmentWindow(const CGTownInstance * townd) : CWindowObject(PLAYER_COLORED | BORDERED), town(townd)
{
OBJ_CONSTRUCTION_CAPTURING_ALL;
initWindow();
setButtons();
setCreaturePurhaseCards();
maxAllCards(cards);
}

View File

@ -0,0 +1,44 @@
/*
* QuickRecruitmentWindow.h, part of VCMI engine
*
* Authors: listed in file AUTHORS in main folder
*
* License: GNU General Public License v2.0 or later
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "../widgets/CGarrisonInt.h"
class CButton;
class CreatureCostBox;
class CreaturePurhaseCard;
class CFilledTexture;
class QuickRecruitmentWindow : public CWindowObject
{
public:
int getAvailableCreatures();
void updateAllSliders();
QuickRecruitmentWindow(const CGTownInstance * townd);
private:
void initWindow();
void setButtons();
void setCancelButton();
void setBuyButton();
void setMaxButton();
void setCreaturePurhaseCards();
void maxAllCards(std::vector<std::shared_ptr<CreaturePurhaseCard>> cards);
void maxAllSlidersAmount(std::vector<std::shared_ptr<CreaturePurhaseCard>> cards);
void purhaseUnits();
const CGTownInstance * town;
std::shared_ptr<CButton> maxButton, buyButton, cancelButton;
std::shared_ptr<CreatureCostBox> totalCost;
std::vector<std::shared_ptr<CreaturePurhaseCard>> cards;
std::shared_ptr<CFilledTexture> backgroundTexture;
};