mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
moved to widgets/markets
This commit is contained in:
@@ -96,14 +96,12 @@ set(client_SRCS
|
|||||||
renderSDL/SDL_Extensions.cpp
|
renderSDL/SDL_Extensions.cpp
|
||||||
|
|
||||||
widgets/Buttons.cpp
|
widgets/Buttons.cpp
|
||||||
widgets/CAltar.cpp
|
|
||||||
widgets/CArtifactHolder.cpp
|
widgets/CArtifactHolder.cpp
|
||||||
widgets/CComponent.cpp
|
widgets/CComponent.cpp
|
||||||
widgets/CExchangeController.cpp
|
widgets/CExchangeController.cpp
|
||||||
widgets/CGarrisonInt.cpp
|
widgets/CGarrisonInt.cpp
|
||||||
widgets/CreatureCostBox.cpp
|
widgets/CreatureCostBox.cpp
|
||||||
widgets/ComboBox.cpp
|
widgets/ComboBox.cpp
|
||||||
widgets/CTradeBase.cpp
|
|
||||||
widgets/Images.cpp
|
widgets/Images.cpp
|
||||||
widgets/MiscWidgets.cpp
|
widgets/MiscWidgets.cpp
|
||||||
widgets/ObjectLists.cpp
|
widgets/ObjectLists.cpp
|
||||||
@@ -118,6 +116,10 @@ set(client_SRCS
|
|||||||
widgets/CArtifactsOfHeroBackpack.cpp
|
widgets/CArtifactsOfHeroBackpack.cpp
|
||||||
widgets/CWindowWithArtifacts.cpp
|
widgets/CWindowWithArtifacts.cpp
|
||||||
widgets/RadialMenu.cpp
|
widgets/RadialMenu.cpp
|
||||||
|
widgets/markets/CAltarArtifacts.cpp
|
||||||
|
widgets/markets/CAltarCreatures.cpp
|
||||||
|
widgets/markets/CTradeBase.cpp
|
||||||
|
widgets/markets/TradePanels.cpp
|
||||||
|
|
||||||
windows/CAltarWindow.cpp
|
windows/CAltarWindow.cpp
|
||||||
windows/CCastleInterface.cpp
|
windows/CCastleInterface.cpp
|
||||||
@@ -269,14 +271,12 @@ set(client_HEADERS
|
|||||||
renderSDL/SDL_PixelAccess.h
|
renderSDL/SDL_PixelAccess.h
|
||||||
|
|
||||||
widgets/Buttons.h
|
widgets/Buttons.h
|
||||||
widgets/CAltar.h
|
|
||||||
widgets/CArtifactHolder.h
|
widgets/CArtifactHolder.h
|
||||||
widgets/CComponent.h
|
widgets/CComponent.h
|
||||||
widgets/CExchangeController.h
|
widgets/CExchangeController.h
|
||||||
widgets/CGarrisonInt.h
|
widgets/CGarrisonInt.h
|
||||||
widgets/CreatureCostBox.h
|
widgets/CreatureCostBox.h
|
||||||
widgets/ComboBox.h
|
widgets/ComboBox.h
|
||||||
widgets/CTradeBase.h
|
|
||||||
widgets/Images.h
|
widgets/Images.h
|
||||||
widgets/MiscWidgets.h
|
widgets/MiscWidgets.h
|
||||||
widgets/ObjectLists.h
|
widgets/ObjectLists.h
|
||||||
@@ -291,6 +291,10 @@ set(client_HEADERS
|
|||||||
widgets/CArtifactsOfHeroBackpack.h
|
widgets/CArtifactsOfHeroBackpack.h
|
||||||
widgets/CWindowWithArtifacts.h
|
widgets/CWindowWithArtifacts.h
|
||||||
widgets/RadialMenu.h
|
widgets/RadialMenu.h
|
||||||
|
widgets/markets/CAltarArtifacts.h
|
||||||
|
widgets/markets/CAltarCreatures.h
|
||||||
|
widgets/markets/CTradeBase.h
|
||||||
|
widgets/markets/TradePanels.h
|
||||||
|
|
||||||
windows/CAltarWindow.h
|
windows/CAltarWindow.h
|
||||||
windows/CCastleInterface.h
|
windows/CCastleInterface.h
|
||||||
|
@@ -1,431 +0,0 @@
|
|||||||
/*
|
|
||||||
* CAltarWindow.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 "CAltar.h"
|
|
||||||
|
|
||||||
#include "../gui/CGuiHandler.h"
|
|
||||||
#include "../gui/CursorHandler.h"
|
|
||||||
#include "../widgets/Buttons.h"
|
|
||||||
#include "../widgets/Slider.h"
|
|
||||||
#include "../widgets/TextControls.h"
|
|
||||||
|
|
||||||
#include "../CGameInfo.h"
|
|
||||||
#include "../CPlayerInterface.h"
|
|
||||||
|
|
||||||
#include "../../CCallback.h"
|
|
||||||
|
|
||||||
#include "../../lib/networkPacks/ArtifactLocation.h"
|
|
||||||
#include "../../lib/CGeneralTextHandler.h"
|
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
|
||||||
#include "../../lib/mapObjects/CGMarket.h"
|
|
||||||
|
|
||||||
CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
|
|
||||||
: CTradeBase(market, hero)
|
|
||||||
{
|
|
||||||
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
|
||||||
|
|
||||||
labels.emplace_back(std::make_shared<CLabel>(450, 34, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477]));
|
|
||||||
labels.emplace_back(std::make_shared<CLabel>(302, 423, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478]));
|
|
||||||
selectedCost = std::make_shared<CLabel>(302, 500, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
|
||||||
selectedArt = std::make_shared<CArtPlace>(Point(280, 442));
|
|
||||||
|
|
||||||
sacrificeAllButton = std::make_shared<CButton>(Point(393, 520), AnimationPath::builtin("ALTFILL.DEF"),
|
|
||||||
CGI->generaltexth->zelp[571], std::bind(&CExpAltar::sacrificeAll, this));
|
|
||||||
sacrificeAllButton->block(hero->artifactsInBackpack.empty() && hero->artifactsWorn.empty());
|
|
||||||
|
|
||||||
sacrificeBackpackButton = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("ALTEMBK.DEF"),
|
|
||||||
CGI->generaltexth->zelp[570], std::bind(&CAltarArtifacts::sacrificeBackpack, this));
|
|
||||||
sacrificeBackpackButton->block(hero->artifactsInBackpack.empty());
|
|
||||||
|
|
||||||
arts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -11));
|
|
||||||
arts->setHero(hero);
|
|
||||||
|
|
||||||
int slotNum = 0;
|
|
||||||
for(auto & altarSlotPos : posSlotsAltar)
|
|
||||||
{
|
|
||||||
auto altarSlot = std::make_shared<CTradeableItem>(altarSlotPos, EType::ARTIFACT_PLACEHOLDER, -1, false, slotNum++);
|
|
||||||
altarSlot->clickPressedCallback = std::bind(&CAltarArtifacts::onSlotClickPressed, this, _1);
|
|
||||||
altarSlot->subtitle = "";
|
|
||||||
items.front().emplace_back(altarSlot);
|
|
||||||
}
|
|
||||||
|
|
||||||
calcExpAltarForHero();
|
|
||||||
deselect();
|
|
||||||
};
|
|
||||||
|
|
||||||
TExpType CAltarArtifacts::calcExpAltarForHero()
|
|
||||||
{
|
|
||||||
auto artifactsOfHero = std::dynamic_pointer_cast<CArtifactsOfHeroAltar>(arts);
|
|
||||||
TExpType expOnAltar(0);
|
|
||||||
for(const auto art : artifactsOfHero->artifactsOnAltar)
|
|
||||||
{
|
|
||||||
int dmp, expOfArt;
|
|
||||||
market->getOffer(art->artType->getId(), 0, dmp, expOfArt, EMarketMode::ARTIFACT_EXP);
|
|
||||||
expOnAltar += expOfArt;
|
|
||||||
}
|
|
||||||
auto resultExp = hero->calculateXp(expOnAltar);
|
|
||||||
expForHero->setText(std::to_string(resultExp));
|
|
||||||
return resultExp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarArtifacts::makeDeal()
|
|
||||||
{
|
|
||||||
std::vector<TradeItemSell> positions;
|
|
||||||
for(const auto art : arts->artifactsOnAltar)
|
|
||||||
{
|
|
||||||
positions.push_back(hero->getSlotByInstance(art));
|
|
||||||
}
|
|
||||||
std::sort(positions.begin(), positions.end());
|
|
||||||
std::reverse(positions.begin(), positions.end());
|
|
||||||
|
|
||||||
LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
|
|
||||||
arts->artifactsOnAltar.clear();
|
|
||||||
|
|
||||||
for(auto item : items[0])
|
|
||||||
{
|
|
||||||
item->setID(-1);
|
|
||||||
item->subtitle = "";
|
|
||||||
}
|
|
||||||
deal->block(true);
|
|
||||||
calcExpAltarForHero();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarArtifacts::sacrificeAll()
|
|
||||||
{
|
|
||||||
std::vector<ConstTransitivePtr<CArtifactInstance>> artsForMove;
|
|
||||||
for(const auto & slotInfo : arts->getHero()->artifactsWorn)
|
|
||||||
{
|
|
||||||
if(!slotInfo.second.locked && slotInfo.second.artifact->artType->isTradable())
|
|
||||||
artsForMove.push_back(slotInfo.second.artifact);
|
|
||||||
}
|
|
||||||
for(auto artInst : artsForMove)
|
|
||||||
moveArtToAltar(nullptr, artInst);
|
|
||||||
arts->updateWornSlots();
|
|
||||||
sacrificeBackpack();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarArtifacts::sacrificeBackpack()
|
|
||||||
{
|
|
||||||
while(!arts->visibleArtSet.artifactsInBackpack.empty())
|
|
||||||
{
|
|
||||||
if(!putArtOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact))
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
calcExpAltarForHero();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarArtifacts::setSelectedArtifact(const CArtifactInstance * art)
|
|
||||||
{
|
|
||||||
if(art)
|
|
||||||
{
|
|
||||||
selectedArt->setArtifact(art);
|
|
||||||
int dmp, exp;
|
|
||||||
market->getOffer(art->getTypeId(), 0, dmp, exp, EMarketMode::ARTIFACT_EXP);
|
|
||||||
selectedCost->setText(std::to_string(hero->calculateXp(exp)));
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
selectedArt->setArtifact(nullptr);
|
|
||||||
selectedCost->setText("");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarArtifacts::moveArtToAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art)
|
|
||||||
{
|
|
||||||
if(putArtOnAltar(altarSlot, art))
|
|
||||||
{
|
|
||||||
CCS->curh->dragAndDropCursor(nullptr);
|
|
||||||
arts->unmarkSlots();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::shared_ptr<CArtifactsOfHeroAltar> CAltarArtifacts::getAOHset() const
|
|
||||||
{
|
|
||||||
return arts;
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAltarArtifacts::putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art)
|
|
||||||
{
|
|
||||||
if(!art->artType->isTradable())
|
|
||||||
{
|
|
||||||
logGlobal->warn("Cannot put special artifact on altar!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!altarSlot || altarSlot->id != -1)
|
|
||||||
{
|
|
||||||
int slotIndex = -1;
|
|
||||||
while(items[0][++slotIndex]->id >= 0 && slotIndex + 1 < items[0].size());
|
|
||||||
slotIndex = items[0][slotIndex]->id == -1 ? slotIndex : -1;
|
|
||||||
if(slotIndex < 0)
|
|
||||||
{
|
|
||||||
logGlobal->warn("No free slots on altar!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
altarSlot = items[0][slotIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
int dmp, exp;
|
|
||||||
market->getOffer(art->artType->getId(), 0, dmp, exp, EMarketMode::ARTIFACT_EXP);
|
|
||||||
exp = static_cast<int>(hero->calculateXp(exp));
|
|
||||||
|
|
||||||
arts->artifactsOnAltar.insert(art);
|
|
||||||
altarSlot->setArtInstance(art);
|
|
||||||
altarSlot->subtitle = std::to_string(exp);
|
|
||||||
|
|
||||||
deal->block(false);
|
|
||||||
return true;
|
|
||||||
};
|
|
||||||
|
|
||||||
void CAltarArtifacts::onSlotClickPressed(std::shared_ptr<CTradeableItem> altarSlot)
|
|
||||||
{
|
|
||||||
const auto pickedArtInst = arts->getPickedArtifact();
|
|
||||||
if(pickedArtInst)
|
|
||||||
{
|
|
||||||
arts->pickedArtMoveToAltar(ArtifactPosition::TRANSITION_POS);
|
|
||||||
moveArtToAltar(altarSlot, pickedArtInst);
|
|
||||||
}
|
|
||||||
else if(const CArtifactInstance * art = altarSlot->getArtInstance())
|
|
||||||
{
|
|
||||||
const auto hero = arts->getHero();
|
|
||||||
const auto slot = hero->getSlotByInstance(art);
|
|
||||||
assert(slot != ArtifactPosition::PRE_FIRST);
|
|
||||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, slot),
|
|
||||||
ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS));
|
|
||||||
arts->pickedArtFromSlot = slot;
|
|
||||||
arts->artifactsOnAltar.erase(art);
|
|
||||||
altarSlot->setID(-1);
|
|
||||||
altarSlot->subtitle.clear();
|
|
||||||
deal->block(!arts->artifactsOnAltar.size());
|
|
||||||
}
|
|
||||||
calcExpAltarForHero();
|
|
||||||
}
|
|
||||||
|
|
||||||
CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
|
|
||||||
: CTradeBase(market, hero)
|
|
||||||
{
|
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
|
||||||
|
|
||||||
labels.emplace_back(std::make_shared<CLabel>(155, 30, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW,
|
|
||||||
boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->getNameTranslated())));
|
|
||||||
labels.emplace_back(std::make_shared<CLabel>(450, 30, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[479]));
|
|
||||||
texts.emplace_back(std::make_unique<CTextBox>(CGI->generaltexth->allTexts[480], Rect(320, 56, 256, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
|
|
||||||
lSubtitle = std::make_shared<CLabel>(180, 503, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
|
||||||
rSubtitle = std::make_shared<CLabel>(426, 503, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
|
||||||
|
|
||||||
offerSlider = std::make_shared<CSlider>(Point(231, 481), 137, std::bind(&CAltarCreatures::onOfferSliderMoved, this, _1), 0, 0, 0, Orientation::HORIZONTAL);
|
|
||||||
maxUnits = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("IRCBTNS.DEF"), CGI->generaltexth->zelp[578], std::bind(&CSlider::scrollToMax, offerSlider));
|
|
||||||
|
|
||||||
unitsOnAltar.resize(GameConstants::ARMY_SIZE, 0);
|
|
||||||
expPerUnit.resize(GameConstants::ARMY_SIZE, 0);
|
|
||||||
sacrificeAllButton = std::make_shared<CButton>(
|
|
||||||
Point(393, 520), AnimationPath::builtin("ALTARMY.DEF"), CGI->generaltexth->zelp[579], std::bind(&CExpAltar::sacrificeAll, this));
|
|
||||||
|
|
||||||
// Hero creatures panel
|
|
||||||
assert(leftTradePanel);
|
|
||||||
leftTradePanel->moveBy(Point(45, 110));
|
|
||||||
leftTradePanel->updateSlotsCallback = std::bind(&CCreaturesSelling::updateSubtitle, this);
|
|
||||||
|
|
||||||
// Altar creatures panel
|
|
||||||
rightTradePanel = std::make_shared<SCreaturesPanel>([this](std::shared_ptr<CTradeableItem> altarSlot) -> void
|
|
||||||
{
|
|
||||||
onSlotClickPressed(altarSlot, hRight);
|
|
||||||
}, leftTradePanel->slots);
|
|
||||||
rightTradePanel->moveBy(Point(334, 110));
|
|
||||||
|
|
||||||
leftTradePanel->deleteSlotsCheck = rightTradePanel->deleteSlotsCheck = std::bind(&CCreaturesSelling::slotDeletingCheck, this, _1);
|
|
||||||
readExpValues();
|
|
||||||
calcExpAltarForHero();
|
|
||||||
deselect();
|
|
||||||
};
|
|
||||||
|
|
||||||
void CAltarCreatures::readExpValues()
|
|
||||||
{
|
|
||||||
int dump;
|
|
||||||
for(auto heroSlot : leftTradePanel->slots)
|
|
||||||
{
|
|
||||||
if(heroSlot->id >= 0)
|
|
||||||
market->getOffer(heroSlot->id, 0, dump, expPerUnit[heroSlot->serial], EMarketMode::CREATURE_EXP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::updateControls()
|
|
||||||
{
|
|
||||||
int sliderAmount = 0;
|
|
||||||
if(hLeft)
|
|
||||||
{
|
|
||||||
std::optional<SlotID> lastSlot;
|
|
||||||
for(auto slot = SlotID(0); slot.num < GameConstants::ARMY_SIZE; slot++)
|
|
||||||
{
|
|
||||||
if(hero->getStackCount(slot) > unitsOnAltar[slot.num])
|
|
||||||
{
|
|
||||||
if(lastSlot.has_value())
|
|
||||||
{
|
|
||||||
lastSlot = std::nullopt;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
lastSlot = slot;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
sliderAmount = hero->getStackCount(SlotID(hLeft->serial));
|
|
||||||
if(lastSlot.has_value() && lastSlot.value() == SlotID(hLeft->serial))
|
|
||||||
sliderAmount--;
|
|
||||||
}
|
|
||||||
offerSlider->setAmount(sliderAmount);
|
|
||||||
offerSlider->block(!offerSlider->getAmount());
|
|
||||||
if(hLeft)
|
|
||||||
offerSlider->scrollTo(unitsOnAltar[hLeft->serial]);
|
|
||||||
maxUnits->block(offerSlider->getAmount() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::updateSubtitlesForSelected()
|
|
||||||
{
|
|
||||||
if(hLeft)
|
|
||||||
lSubtitle->setText(std::to_string(offerSlider->getValue()));
|
|
||||||
else
|
|
||||||
lSubtitle->setText("");
|
|
||||||
if(hRight)
|
|
||||||
rSubtitle->setText(hRight->subtitle);
|
|
||||||
else
|
|
||||||
rSubtitle->setText("");
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::updateSlots()
|
|
||||||
{
|
|
||||||
rightTradePanel->deleteSlots();
|
|
||||||
leftTradePanel->deleteSlots();
|
|
||||||
assert(leftTradePanel->slots.size() == rightTradePanel->slots.size());
|
|
||||||
readExpValues();
|
|
||||||
leftTradePanel->updateSlots();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::deselect()
|
|
||||||
{
|
|
||||||
CTradeBase::deselect();
|
|
||||||
offerSlider->block(true);
|
|
||||||
maxUnits->block(true);
|
|
||||||
updateSubtitlesForSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
TExpType CAltarCreatures::calcExpAltarForHero()
|
|
||||||
{
|
|
||||||
TExpType expOnAltar(0);
|
|
||||||
auto oneUnitExp = expPerUnit.begin();
|
|
||||||
for(const auto units : unitsOnAltar)
|
|
||||||
expOnAltar += *oneUnitExp++ * units;
|
|
||||||
auto resultExp = hero->calculateXp(expOnAltar);
|
|
||||||
expForHero->setText(std::to_string(resultExp));
|
|
||||||
return resultExp;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::makeDeal()
|
|
||||||
{
|
|
||||||
deselect();
|
|
||||||
offerSlider->scrollTo(0);
|
|
||||||
expForHero->setText(std::to_string(0));
|
|
||||||
|
|
||||||
std::vector<TradeItemSell> ids;
|
|
||||||
std::vector<ui32> toSacrifice;
|
|
||||||
|
|
||||||
for(int i = 0; i < unitsOnAltar.size(); i++)
|
|
||||||
{
|
|
||||||
if(unitsOnAltar[i])
|
|
||||||
{
|
|
||||||
ids.push_back(SlotID(i));
|
|
||||||
toSacrifice.push_back(unitsOnAltar[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCPLINT->cb->trade(market, EMarketMode::CREATURE_EXP, ids, {}, toSacrifice, hero);
|
|
||||||
|
|
||||||
for(int & units : unitsOnAltar)
|
|
||||||
units = 0;
|
|
||||||
|
|
||||||
for(auto heroSlot : rightTradePanel->slots)
|
|
||||||
{
|
|
||||||
heroSlot->setType(CREATURE_PLACEHOLDER);
|
|
||||||
heroSlot->subtitle.clear();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::sacrificeAll()
|
|
||||||
{
|
|
||||||
std::optional<SlotID> lastSlot;
|
|
||||||
for(auto heroSlot : leftTradePanel->slots)
|
|
||||||
{
|
|
||||||
auto stackCount = hero->getStackCount(SlotID(heroSlot->serial));
|
|
||||||
if(stackCount > unitsOnAltar[heroSlot->serial])
|
|
||||||
{
|
|
||||||
if(!lastSlot.has_value())
|
|
||||||
lastSlot = SlotID(heroSlot->serial);
|
|
||||||
unitsOnAltar[heroSlot->serial] = stackCount;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
assert(lastSlot.has_value());
|
|
||||||
unitsOnAltar[lastSlot.value().num]--;
|
|
||||||
|
|
||||||
if(hRight)
|
|
||||||
offerSlider->scrollTo(unitsOnAltar[hRight->serial]);
|
|
||||||
for(auto altarSlot : rightTradePanel->slots)
|
|
||||||
updateAltarSlot(altarSlot);
|
|
||||||
updateSubtitlesForSelected();
|
|
||||||
|
|
||||||
deal->block(calcExpAltarForHero() == 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::updateAltarSlot(std::shared_ptr<CTradeableItem> slot)
|
|
||||||
{
|
|
||||||
auto units = unitsOnAltar[slot->serial];
|
|
||||||
slot->setType(units > 0 ? CREATURE : CREATURE_PLACEHOLDER);
|
|
||||||
slot->subtitle = units > 0 ?
|
|
||||||
boost::str(boost::format(CGI->generaltexth->allTexts[122]) % std::to_string(hero->calculateXp(units * expPerUnit[slot->serial]))) : "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::onOfferSliderMoved(int newVal)
|
|
||||||
{
|
|
||||||
if(hLeft)
|
|
||||||
unitsOnAltar[hLeft->serial] = newVal;
|
|
||||||
if(hRight)
|
|
||||||
updateAltarSlot(hRight);
|
|
||||||
deal->block(calcExpAltarForHero() == 0);
|
|
||||||
updateControls();
|
|
||||||
updateSubtitlesForSelected();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarCreatures::onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSide)
|
|
||||||
{
|
|
||||||
if(hCurSide == newSlot)
|
|
||||||
return;
|
|
||||||
|
|
||||||
auto * oppositeSlot = &hLeft;
|
|
||||||
auto oppositePanel = leftTradePanel;
|
|
||||||
CTradeBase::onSlotClickPressed(newSlot, hCurSide);
|
|
||||||
if(hCurSide == hLeft)
|
|
||||||
{
|
|
||||||
oppositeSlot = &hRight;
|
|
||||||
oppositePanel = rightTradePanel;
|
|
||||||
}
|
|
||||||
std::shared_ptr<CTradeableItem> oppositeNewSlot;
|
|
||||||
for(const auto & slot : oppositePanel->slots)
|
|
||||||
if(slot->serial == newSlot->serial)
|
|
||||||
{
|
|
||||||
oppositeNewSlot = slot;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
assert(oppositeNewSlot);
|
|
||||||
CTradeBase::onSlotClickPressed(oppositeNewSlot, *oppositeSlot);
|
|
||||||
updateControls();
|
|
||||||
updateSubtitlesForSelected();
|
|
||||||
redraw();
|
|
||||||
}
|
|
@@ -20,10 +20,10 @@ CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position)
|
|||||||
position,
|
position,
|
||||||
std::bind(&CArtifactsOfHeroMarket::scrollBackpack, this, _1));
|
std::bind(&CArtifactsOfHeroMarket::scrollBackpack, this, _1));
|
||||||
|
|
||||||
for(auto slot : artWorn)
|
for(const auto & [slot, artPlace] : artWorn)
|
||||||
slot.second->selection->lineWidth = 2;
|
artPlace->selection->setBorderWidth(2);
|
||||||
for(auto slot : backpack)
|
for(auto artPlace : backpack)
|
||||||
slot->selection->lineWidth = 2;
|
artPlace->selection->setBorderWidth(2);
|
||||||
};
|
};
|
||||||
|
|
||||||
void CArtifactsOfHeroMarket::scrollBackpack(int offset)
|
void CArtifactsOfHeroMarket::scrollBackpack(int offset)
|
||||||
|
@@ -1,195 +0,0 @@
|
|||||||
/*
|
|
||||||
* CTradeBase.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 "Images.h"
|
|
||||||
|
|
||||||
#include "../lib/FunctionList.h"
|
|
||||||
#include "../lib/networkPacks/TradeItem.h"
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
|
||||||
|
|
||||||
class IMarket;
|
|
||||||
class CGHeroInstance;
|
|
||||||
class SelectableSlot;
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
|
||||||
|
|
||||||
class CButton;
|
|
||||||
class CTextBox;
|
|
||||||
class CSlider;
|
|
||||||
|
|
||||||
enum EType
|
|
||||||
{
|
|
||||||
RESOURCE, PLAYER, ARTIFACT_TYPE, CREATURE, CREATURE_PLACEHOLDER, ARTIFACT_PLACEHOLDER, ARTIFACT_INSTANCE
|
|
||||||
};
|
|
||||||
|
|
||||||
class CTradeableItem : public CIntObject, public std::enable_shared_from_this<CTradeableItem>
|
|
||||||
{
|
|
||||||
std::shared_ptr<CAnimImage> image;
|
|
||||||
AnimationPath getFilename();
|
|
||||||
int getIndex();
|
|
||||||
public:
|
|
||||||
using ClickPressedFunctor = std::function<void(std::shared_ptr<CTradeableItem>)>;
|
|
||||||
|
|
||||||
const CArtifactInstance * hlp; //holds ptr to artifact instance id type artifact
|
|
||||||
EType type;
|
|
||||||
int id;
|
|
||||||
const int serial;
|
|
||||||
const bool left;
|
|
||||||
std::string subtitle; //empty if default
|
|
||||||
ClickPressedFunctor clickPressedCallback;
|
|
||||||
|
|
||||||
void setType(EType newType);
|
|
||||||
void setID(int newID);
|
|
||||||
|
|
||||||
const CArtifactInstance * getArtInstance() const;
|
|
||||||
void setArtInstance(const CArtifactInstance * art);
|
|
||||||
|
|
||||||
std::unique_ptr<SelectableSlot> selection;
|
|
||||||
bool downSelection;
|
|
||||||
|
|
||||||
void showAllAt(const Point & dstPos, const std::string & customSub, Canvas & to);
|
|
||||||
|
|
||||||
void showPopupWindow(const Point & cursorPosition) override;
|
|
||||||
void hover(bool on) override;
|
|
||||||
void showAll(Canvas & to) override;
|
|
||||||
void clickPressed(const Point & cursorPosition) override;
|
|
||||||
std::string getName(int number = -1) const;
|
|
||||||
CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct STradePanel : public CIntObject
|
|
||||||
{
|
|
||||||
using UpdateSlotsFunctor = std::function<void()>;
|
|
||||||
using DeleteSlotsCheck = std::function<bool(std::shared_ptr<CTradeableItem> & slot)>;
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<CTradeableItem>> slots;
|
|
||||||
UpdateSlotsFunctor updateSlotsCallback;
|
|
||||||
DeleteSlotsCheck deleteSlotsCheck;
|
|
||||||
std::shared_ptr<CTradeableItem> selected;
|
|
||||||
const int selectionWidth = 2;
|
|
||||||
|
|
||||||
virtual void updateSlots();
|
|
||||||
virtual void deselect();
|
|
||||||
virtual void clearSubtitles();
|
|
||||||
void updateOffer(CTradeableItem & slot, int, int);
|
|
||||||
void deleteSlots();
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SResourcesPanel : public STradePanel
|
|
||||||
{
|
|
||||||
const std::vector<GameResID> resourcesForTrade =
|
|
||||||
{
|
|
||||||
GameResID::WOOD, GameResID::MERCURY, GameResID::ORE,
|
|
||||||
GameResID::SULFUR, GameResID::CRYSTAL, GameResID::GEMS,
|
|
||||||
GameResID::GOLD
|
|
||||||
};
|
|
||||||
const std::vector<Point> slotsPos =
|
|
||||||
{
|
|
||||||
Point(0, 0), Point(83, 0), Point(166, 0),
|
|
||||||
Point(0, 79), Point(83, 79), Point(166, 79),
|
|
||||||
Point(83, 158)
|
|
||||||
};
|
|
||||||
|
|
||||||
SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SArtifactsPanel : public STradePanel
|
|
||||||
{
|
|
||||||
const std::vector<Point> slotsPos =
|
|
||||||
{
|
|
||||||
Point(0, 0), Point(83, 0), Point(166, 0),
|
|
||||||
Point(0, 79), Point(83, 79), Point(166, 79),
|
|
||||||
Point(83, 158)
|
|
||||||
};
|
|
||||||
const size_t slotsForTrade = 7;
|
|
||||||
|
|
||||||
SArtifactsPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles,
|
|
||||||
std::vector<TradeItemBuy> & arts);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SPlayersPanel : public STradePanel
|
|
||||||
{
|
|
||||||
const std::vector<Point> slotsPos =
|
|
||||||
{
|
|
||||||
Point(0, 0), Point(83, 0), Point(166, 0),
|
|
||||||
Point(0, 118), Point(83, 118), Point(166, 118),
|
|
||||||
Point(83, 236)
|
|
||||||
};
|
|
||||||
SPlayersPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback);
|
|
||||||
};
|
|
||||||
|
|
||||||
struct SCreaturesPanel : public STradePanel
|
|
||||||
{
|
|
||||||
using slotsData = std::vector<std::tuple<CreatureID, SlotID, int>>;
|
|
||||||
|
|
||||||
const std::vector<Point> slotsPos =
|
|
||||||
{
|
|
||||||
Point(0, 0), Point(83, 0), Point(166, 0),
|
|
||||||
Point(0, 98), Point(83, 98), Point(166, 98),
|
|
||||||
Point(83, 196)
|
|
||||||
};
|
|
||||||
SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, slotsData & initialSlots);
|
|
||||||
SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback,
|
|
||||||
std::vector<std::shared_ptr<CTradeableItem>> & stsSlots, bool emptySlots = true);
|
|
||||||
};
|
|
||||||
|
|
||||||
class CTradeBase
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
const IMarket * market;
|
|
||||||
const CGHeroInstance * hero;
|
|
||||||
|
|
||||||
//all indexes: 1 = left, 0 = right
|
|
||||||
std::array<std::vector<std::shared_ptr<CTradeableItem>>, 2> items;
|
|
||||||
std::shared_ptr<STradePanel> leftTradePanel, rightTradePanel;
|
|
||||||
|
|
||||||
//highlighted items (nullptr if no highlight)
|
|
||||||
std::shared_ptr<CTradeableItem> hLeft;
|
|
||||||
std::shared_ptr<CTradeableItem> hRight;
|
|
||||||
std::shared_ptr<CButton> deal;
|
|
||||||
std::shared_ptr<CSlider> offerSlider;
|
|
||||||
|
|
||||||
CTradeBase(const IMarket * market, const CGHeroInstance * hero);
|
|
||||||
void removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove);
|
|
||||||
void removeItem(std::shared_ptr<CTradeableItem> item);
|
|
||||||
void getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRemove);
|
|
||||||
virtual void makeDeal() = 0;
|
|
||||||
virtual void deselect();
|
|
||||||
virtual void onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot);
|
|
||||||
|
|
||||||
protected:
|
|
||||||
std::vector<std::shared_ptr<CLabel>> labels;
|
|
||||||
std::vector<std::shared_ptr<CButton>> buttons;
|
|
||||||
std::vector<std::shared_ptr<CTextBox>> texts;
|
|
||||||
};
|
|
||||||
|
|
||||||
// Market subclasses
|
|
||||||
class CExpAltar : virtual public CTradeBase, virtual public CIntObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::shared_ptr<CLabel> expToLevel;
|
|
||||||
std::shared_ptr<CLabel> expForHero;
|
|
||||||
std::shared_ptr<CButton> sacrificeAllButton;
|
|
||||||
const Point dealButtonPos = Point(269, 520);
|
|
||||||
|
|
||||||
CExpAltar();
|
|
||||||
virtual void sacrificeAll() = 0;
|
|
||||||
virtual TExpType calcExpAltarForHero() = 0;
|
|
||||||
};
|
|
||||||
|
|
||||||
class CCreaturesSelling : virtual public CTradeBase, virtual public CIntObject
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CCreaturesSelling();
|
|
||||||
bool slotDeletingCheck(std::shared_ptr<CTradeableItem> & slot);
|
|
||||||
void updateSubtitle();
|
|
||||||
};
|
|
213
client/widgets/markets/CAltarArtifacts.cpp
Normal file
213
client/widgets/markets/CAltarArtifacts.cpp
Normal file
@@ -0,0 +1,213 @@
|
|||||||
|
/*
|
||||||
|
* CAltarArtifacts.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 "CAltarArtifacts.h"
|
||||||
|
|
||||||
|
#include "../../gui/CGuiHandler.h"
|
||||||
|
#include "../../gui/CursorHandler.h"
|
||||||
|
#include "../../widgets/Buttons.h"
|
||||||
|
#include "../../widgets/TextControls.h"
|
||||||
|
|
||||||
|
#include "../../CGameInfo.h"
|
||||||
|
#include "../../CPlayerInterface.h"
|
||||||
|
|
||||||
|
#include "../../../CCallback.h"
|
||||||
|
|
||||||
|
#include "../../../lib/networkPacks/ArtifactLocation.h"
|
||||||
|
#include "../../../lib/CGeneralTextHandler.h"
|
||||||
|
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../../lib/mapObjects/CGMarket.h"
|
||||||
|
|
||||||
|
CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
: CTradeBase(market, hero)
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
|
labels.emplace_back(std::make_shared<CLabel>(450, 34, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477]));
|
||||||
|
labels.emplace_back(std::make_shared<CLabel>(302, 423, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478]));
|
||||||
|
selectedCost = std::make_shared<CLabel>(302, 500, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||||
|
selectedArt = std::make_shared<CArtPlace>(Point(280, 442));
|
||||||
|
|
||||||
|
sacrificeAllButton = std::make_shared<CButton>(Point(393, 520), AnimationPath::builtin("ALTFILL.DEF"),
|
||||||
|
CGI->generaltexth->zelp[571], std::bind(&CExperienceAltar::sacrificeAll, this));
|
||||||
|
sacrificeAllButton->block(hero->artifactsInBackpack.empty() && hero->artifactsWorn.empty());
|
||||||
|
|
||||||
|
sacrificeBackpackButton = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("ALTEMBK.DEF"),
|
||||||
|
CGI->generaltexth->zelp[570], std::bind(&CAltarArtifacts::sacrificeBackpack, this));
|
||||||
|
sacrificeBackpackButton->block(hero->artifactsInBackpack.empty());
|
||||||
|
|
||||||
|
arts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -11));
|
||||||
|
arts->setHero(hero);
|
||||||
|
|
||||||
|
int slotNum = 0;
|
||||||
|
for(auto & altarSlotPos : posSlotsAltar)
|
||||||
|
{
|
||||||
|
auto altarSlot = std::make_shared<CTradeableItem>(altarSlotPos, EType::ARTIFACT_PLACEHOLDER, -1, false, slotNum);
|
||||||
|
altarSlot->clickPressedCallback = std::bind(&CAltarArtifacts::onSlotClickPressed, this, _1, hRight);
|
||||||
|
altarSlot->subtitle.clear();
|
||||||
|
items.front().emplace_back(altarSlot);
|
||||||
|
slotNum++;
|
||||||
|
}
|
||||||
|
|
||||||
|
expForHero->setText(std::to_string(0));
|
||||||
|
CTradeBase::deselect();
|
||||||
|
};
|
||||||
|
|
||||||
|
TExpType CAltarArtifacts::calcExpAltarForHero()
|
||||||
|
{
|
||||||
|
auto artifactsOfHero = std::dynamic_pointer_cast<CArtifactsOfHeroAltar>(arts);
|
||||||
|
TExpType expOnAltar(0);
|
||||||
|
for(const auto art : artifactsOfHero->artifactsOnAltar)
|
||||||
|
{
|
||||||
|
int dmp = 0;
|
||||||
|
int expOfArt = 0;
|
||||||
|
market->getOffer(art->getTypeId(), 0, dmp, expOfArt, EMarketMode::ARTIFACT_EXP);
|
||||||
|
expOnAltar += expOfArt;
|
||||||
|
}
|
||||||
|
auto resultExp = hero->calculateXp(expOnAltar);
|
||||||
|
expForHero->setText(std::to_string(resultExp));
|
||||||
|
return resultExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarArtifacts::makeDeal()
|
||||||
|
{
|
||||||
|
std::vector<TradeItemSell> positions;
|
||||||
|
for(const auto art : arts->artifactsOnAltar)
|
||||||
|
{
|
||||||
|
positions.push_back(hero->getSlotByInstance(art));
|
||||||
|
}
|
||||||
|
std::sort(positions.begin(), positions.end());
|
||||||
|
std::reverse(positions.begin(), positions.end());
|
||||||
|
|
||||||
|
LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
|
||||||
|
arts->artifactsOnAltar.clear();
|
||||||
|
|
||||||
|
for(auto item : items[0])
|
||||||
|
{
|
||||||
|
item->setID(-1);
|
||||||
|
item->subtitle.clear();
|
||||||
|
}
|
||||||
|
deal->block(true);
|
||||||
|
calcExpAltarForHero();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarArtifacts::sacrificeAll()
|
||||||
|
{
|
||||||
|
std::vector<ConstTransitivePtr<CArtifactInstance>> artsForMove;
|
||||||
|
for(const auto & [slot, slotInfo] : arts->getHero()->artifactsWorn)
|
||||||
|
{
|
||||||
|
if(!slotInfo.locked && slotInfo.artifact->artType->isTradable())
|
||||||
|
artsForMove.emplace_back(slotInfo.artifact);
|
||||||
|
}
|
||||||
|
for(auto artInst : artsForMove)
|
||||||
|
moveArtToAltar(nullptr, artInst);
|
||||||
|
arts->updateWornSlots();
|
||||||
|
sacrificeBackpack();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarArtifacts::sacrificeBackpack()
|
||||||
|
{
|
||||||
|
while(!arts->visibleArtSet.artifactsInBackpack.empty())
|
||||||
|
{
|
||||||
|
if(!putArtOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact))
|
||||||
|
break;
|
||||||
|
};
|
||||||
|
calcExpAltarForHero();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarArtifacts::setSelectedArtifact(const CArtifactInstance * art)
|
||||||
|
{
|
||||||
|
if(art)
|
||||||
|
{
|
||||||
|
selectedArt->setArtifact(art);
|
||||||
|
int dmp = 0;
|
||||||
|
int exp = 0;
|
||||||
|
market->getOffer(art->getTypeId(), 0, dmp, exp, EMarketMode::ARTIFACT_EXP);
|
||||||
|
selectedCost->setText(std::to_string(hero->calculateXp(exp)));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
selectedArt->setArtifact(nullptr);
|
||||||
|
selectedCost->setText("");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarArtifacts::moveArtToAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art)
|
||||||
|
{
|
||||||
|
if(putArtOnAltar(altarSlot, art))
|
||||||
|
{
|
||||||
|
CCS->curh->dragAndDropCursor(nullptr);
|
||||||
|
arts->unmarkSlots();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
std::shared_ptr<CArtifactsOfHeroAltar> CAltarArtifacts::getAOHset() const
|
||||||
|
{
|
||||||
|
return arts;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CAltarArtifacts::putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art)
|
||||||
|
{
|
||||||
|
if(!art->artType->isTradable())
|
||||||
|
{
|
||||||
|
logGlobal->warn("Cannot put special artifact on altar!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(!altarSlot || altarSlot->id != -1)
|
||||||
|
{
|
||||||
|
int slotIndex = -1;
|
||||||
|
while(items[0][++slotIndex]->id >= 0 && slotIndex + 1 < items[0].size());
|
||||||
|
slotIndex = items[0][slotIndex]->id == -1 ? slotIndex : -1;
|
||||||
|
if(slotIndex < 0)
|
||||||
|
{
|
||||||
|
logGlobal->warn("No free slots on altar!");
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
altarSlot = items[0][slotIndex];
|
||||||
|
}
|
||||||
|
|
||||||
|
int dmp = 0;
|
||||||
|
int exp = 0;
|
||||||
|
market->getOffer(art->artType->getId(), 0, dmp, exp, EMarketMode::ARTIFACT_EXP);
|
||||||
|
exp = static_cast<int>(hero->calculateXp(exp));
|
||||||
|
|
||||||
|
arts->artifactsOnAltar.insert(art);
|
||||||
|
altarSlot->setArtInstance(art);
|
||||||
|
altarSlot->subtitle = std::to_string(exp);
|
||||||
|
|
||||||
|
deal->block(false);
|
||||||
|
return true;
|
||||||
|
};
|
||||||
|
|
||||||
|
void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot)
|
||||||
|
{
|
||||||
|
const auto pickedArtInst = arts->getPickedArtifact();
|
||||||
|
if(pickedArtInst)
|
||||||
|
{
|
||||||
|
arts->pickedArtMoveToAltar(ArtifactPosition::TRANSITION_POS);
|
||||||
|
moveArtToAltar(newSlot, pickedArtInst);
|
||||||
|
}
|
||||||
|
else if(const CArtifactInstance * art = newSlot->getArtInstance())
|
||||||
|
{
|
||||||
|
const auto hero = arts->getHero();
|
||||||
|
const auto slot = hero->getSlotByInstance(art);
|
||||||
|
assert(slot != ArtifactPosition::PRE_FIRST);
|
||||||
|
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, slot),
|
||||||
|
ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS));
|
||||||
|
arts->pickedArtFromSlot = slot;
|
||||||
|
arts->artifactsOnAltar.erase(art);
|
||||||
|
newSlot->setID(-1);
|
||||||
|
newSlot->subtitle.clear();
|
||||||
|
deal->block(!arts->artifactsOnAltar.size());
|
||||||
|
}
|
||||||
|
calcExpAltarForHero();
|
||||||
|
}
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* CAltar.h, part of VCMI engine
|
* CAltarArtifacts.h, part of VCMI engine
|
||||||
*
|
*
|
||||||
* Authors: listed in file AUTHORS in main folder
|
* Authors: listed in file AUTHORS in main folder
|
||||||
*
|
*
|
||||||
@@ -9,10 +9,10 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../widgets/CArtifactsOfHeroAltar.h"
|
#include "../CArtifactsOfHeroAltar.h"
|
||||||
#include "../widgets/CTradeBase.h"
|
#include "CTradeBase.h"
|
||||||
|
|
||||||
class CAltarArtifacts : public CExpAltar
|
class CAltarArtifacts : public CExperienceAltar
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero);
|
CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero);
|
||||||
@@ -43,29 +43,5 @@ private:
|
|||||||
};
|
};
|
||||||
|
|
||||||
bool putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art);
|
bool putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art);
|
||||||
void onSlotClickPressed(std::shared_ptr<CTradeableItem> altarSlot);
|
void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot) override;
|
||||||
};
|
|
||||||
|
|
||||||
class CAltarCreatures : public CExpAltar, public CCreaturesSelling
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
CAltarCreatures(const IMarket * market, const CGHeroInstance * hero);
|
|
||||||
void updateSlots();
|
|
||||||
void deselect() override;
|
|
||||||
TExpType calcExpAltarForHero() override;
|
|
||||||
void makeDeal() override;
|
|
||||||
void sacrificeAll() override;
|
|
||||||
void updateAltarSlot(std::shared_ptr<CTradeableItem> slot);
|
|
||||||
|
|
||||||
private:
|
|
||||||
std::shared_ptr<CButton> maxUnits;
|
|
||||||
std::vector<int> unitsOnAltar;
|
|
||||||
std::vector<int> expPerUnit;
|
|
||||||
std::shared_ptr<CLabel> lSubtitle, rSubtitle;
|
|
||||||
|
|
||||||
void readExpValues();
|
|
||||||
void updateControls();
|
|
||||||
void updateSubtitlesForSelected();
|
|
||||||
void onOfferSliderMoved(int newVal);
|
|
||||||
void onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSide) override;
|
|
||||||
};
|
};
|
247
client/widgets/markets/CAltarCreatures.cpp
Normal file
247
client/widgets/markets/CAltarCreatures.cpp
Normal file
@@ -0,0 +1,247 @@
|
|||||||
|
/*
|
||||||
|
* CAltarCreatures.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 "CAltarCreatures.h"
|
||||||
|
|
||||||
|
#include "../../gui/CGuiHandler.h"
|
||||||
|
#include "../../widgets/Buttons.h"
|
||||||
|
#include "../../widgets/Slider.h"
|
||||||
|
#include "../../widgets/TextControls.h"
|
||||||
|
|
||||||
|
#include "../../CGameInfo.h"
|
||||||
|
#include "../../CPlayerInterface.h"
|
||||||
|
|
||||||
|
#include "../../../CCallback.h"
|
||||||
|
|
||||||
|
#include "../../../lib/CGeneralTextHandler.h"
|
||||||
|
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
#include "../../../lib/mapObjects/CGMarket.h"
|
||||||
|
|
||||||
|
CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
: CTradeBase(market, hero)
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
|
labels.emplace_back(std::make_shared<CLabel>(155, 30, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW,
|
||||||
|
boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->getNameTranslated())));
|
||||||
|
labels.emplace_back(std::make_shared<CLabel>(450, 30, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[479]));
|
||||||
|
texts.emplace_back(std::make_unique<CTextBox>(CGI->generaltexth->allTexts[480], Rect(320, 56, 256, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
|
||||||
|
lSubtitle = std::make_shared<CLabel>(180, 503, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||||
|
rSubtitle = std::make_shared<CLabel>(426, 503, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE);
|
||||||
|
|
||||||
|
offerSlider = std::make_shared<CSlider>(Point(231, 481), 137, std::bind(&CAltarCreatures::onOfferSliderMoved, this, _1), 0, 0, 0, Orientation::HORIZONTAL);
|
||||||
|
maxUnits = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("IRCBTNS.DEF"), CGI->generaltexth->zelp[578], std::bind(&CSlider::scrollToMax, offerSlider));
|
||||||
|
|
||||||
|
unitsOnAltar.resize(GameConstants::ARMY_SIZE, 0);
|
||||||
|
expPerUnit.resize(GameConstants::ARMY_SIZE, 0);
|
||||||
|
sacrificeAllButton = std::make_shared<CButton>(
|
||||||
|
Point(393, 520), AnimationPath::builtin("ALTARMY.DEF"), CGI->generaltexth->zelp[579], std::bind(&CExperienceAltar::sacrificeAll, this));
|
||||||
|
|
||||||
|
// Hero creatures panel
|
||||||
|
assert(leftTradePanel);
|
||||||
|
leftTradePanel->moveBy(Point(45, 110));
|
||||||
|
leftTradePanel->updateSlotsCallback = std::bind(&CCreaturesSelling::updateSubtitle, this);
|
||||||
|
|
||||||
|
// Altar creatures panel
|
||||||
|
rightTradePanel = std::make_shared<CreaturesPanel>([this](const std::shared_ptr<CTradeableItem> & altarSlot)
|
||||||
|
{
|
||||||
|
CAltarCreatures::onSlotClickPressed(altarSlot, hRight);
|
||||||
|
}, leftTradePanel->slots);
|
||||||
|
rightTradePanel->moveBy(Point(334, 110));
|
||||||
|
|
||||||
|
leftTradePanel->deleteSlotsCheck = rightTradePanel->deleteSlotsCheck = std::bind(&CCreaturesSelling::slotDeletingCheck, this, _1);
|
||||||
|
readExpValues();
|
||||||
|
expForHero->setText(std::to_string(0));
|
||||||
|
CAltarCreatures::deselect();
|
||||||
|
};
|
||||||
|
|
||||||
|
void CAltarCreatures::readExpValues()
|
||||||
|
{
|
||||||
|
int dump;
|
||||||
|
for(auto heroSlot : leftTradePanel->slots)
|
||||||
|
{
|
||||||
|
if(heroSlot->id >= 0)
|
||||||
|
market->getOffer(heroSlot->id, 0, dump, expPerUnit[heroSlot->serial], EMarketMode::CREATURE_EXP);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::updateControls()
|
||||||
|
{
|
||||||
|
int sliderAmount = 0;
|
||||||
|
if(hLeft)
|
||||||
|
{
|
||||||
|
std::optional<SlotID> lastSlot;
|
||||||
|
for(auto slot = SlotID(0); slot.num < GameConstants::ARMY_SIZE; slot++)
|
||||||
|
{
|
||||||
|
if(hero->getStackCount(slot) > unitsOnAltar[slot.num])
|
||||||
|
{
|
||||||
|
if(lastSlot.has_value())
|
||||||
|
{
|
||||||
|
lastSlot = std::nullopt;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
lastSlot = slot;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
sliderAmount = hero->getStackCount(SlotID(hLeft->serial));
|
||||||
|
if(lastSlot.has_value() && lastSlot.value() == SlotID(hLeft->serial))
|
||||||
|
sliderAmount--;
|
||||||
|
}
|
||||||
|
offerSlider->setAmount(sliderAmount);
|
||||||
|
offerSlider->block(!offerSlider->getAmount());
|
||||||
|
if(hLeft)
|
||||||
|
offerSlider->scrollTo(unitsOnAltar[hLeft->serial]);
|
||||||
|
maxUnits->block(offerSlider->getAmount() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::updateSubtitlesForSelected()
|
||||||
|
{
|
||||||
|
if(hLeft)
|
||||||
|
lSubtitle->setText(std::to_string(offerSlider->getValue()));
|
||||||
|
else
|
||||||
|
lSubtitle->setText("");
|
||||||
|
if(hRight)
|
||||||
|
rSubtitle->setText(hRight->subtitle);
|
||||||
|
else
|
||||||
|
rSubtitle->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::updateSlots()
|
||||||
|
{
|
||||||
|
rightTradePanel->deleteSlots();
|
||||||
|
leftTradePanel->deleteSlots();
|
||||||
|
assert(leftTradePanel->slots.size() == rightTradePanel->slots.size());
|
||||||
|
readExpValues();
|
||||||
|
leftTradePanel->updateSlots();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::deselect()
|
||||||
|
{
|
||||||
|
CTradeBase::deselect();
|
||||||
|
offerSlider->block(true);
|
||||||
|
maxUnits->block(true);
|
||||||
|
updateSubtitlesForSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
TExpType CAltarCreatures::calcExpAltarForHero()
|
||||||
|
{
|
||||||
|
TExpType expOnAltar(0);
|
||||||
|
auto oneUnitExp = expPerUnit.begin();
|
||||||
|
for(const auto units : unitsOnAltar)
|
||||||
|
expOnAltar += *oneUnitExp++ * units;
|
||||||
|
auto resultExp = hero->calculateXp(expOnAltar);
|
||||||
|
expForHero->setText(std::to_string(resultExp));
|
||||||
|
return resultExp;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::makeDeal()
|
||||||
|
{
|
||||||
|
deselect();
|
||||||
|
offerSlider->scrollTo(0);
|
||||||
|
expForHero->setText(std::to_string(0));
|
||||||
|
|
||||||
|
std::vector<TradeItemSell> ids;
|
||||||
|
std::vector<ui32> toSacrifice;
|
||||||
|
|
||||||
|
for(int i = 0; i < unitsOnAltar.size(); i++)
|
||||||
|
{
|
||||||
|
if(unitsOnAltar[i])
|
||||||
|
{
|
||||||
|
ids.push_back(SlotID(i));
|
||||||
|
toSacrifice.push_back(unitsOnAltar[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
LOCPLINT->cb->trade(market, EMarketMode::CREATURE_EXP, ids, {}, toSacrifice, hero);
|
||||||
|
|
||||||
|
for(int & units : unitsOnAltar)
|
||||||
|
units = 0;
|
||||||
|
|
||||||
|
for(auto heroSlot : rightTradePanel->slots)
|
||||||
|
{
|
||||||
|
heroSlot->setType(EType::CREATURE_PLACEHOLDER);
|
||||||
|
heroSlot->subtitle.clear();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::sacrificeAll()
|
||||||
|
{
|
||||||
|
std::optional<SlotID> lastSlot;
|
||||||
|
for(auto heroSlot : leftTradePanel->slots)
|
||||||
|
{
|
||||||
|
auto stackCount = hero->getStackCount(SlotID(heroSlot->serial));
|
||||||
|
if(stackCount > unitsOnAltar[heroSlot->serial])
|
||||||
|
{
|
||||||
|
if(!lastSlot.has_value())
|
||||||
|
lastSlot = SlotID(heroSlot->serial);
|
||||||
|
unitsOnAltar[heroSlot->serial] = stackCount;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
assert(lastSlot.has_value());
|
||||||
|
unitsOnAltar[lastSlot.value().num]--;
|
||||||
|
|
||||||
|
if(hRight)
|
||||||
|
offerSlider->scrollTo(unitsOnAltar[hRight->serial]);
|
||||||
|
for(auto altarSlot : rightTradePanel->slots)
|
||||||
|
updateAltarSlot(altarSlot);
|
||||||
|
updateSubtitlesForSelected();
|
||||||
|
|
||||||
|
deal->block(calcExpAltarForHero() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::updateAltarSlot(std::shared_ptr<CTradeableItem> slot)
|
||||||
|
{
|
||||||
|
auto units = unitsOnAltar[slot->serial];
|
||||||
|
slot->setType(units > 0 ? EType::CREATURE : EType::CREATURE_PLACEHOLDER);
|
||||||
|
slot->subtitle = units > 0 ?
|
||||||
|
boost::str(boost::format(CGI->generaltexth->allTexts[122]) % std::to_string(hero->calculateXp(units * expPerUnit[slot->serial]))) : "";
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::onOfferSliderMoved(int newVal)
|
||||||
|
{
|
||||||
|
if(hLeft)
|
||||||
|
unitsOnAltar[hLeft->serial] = newVal;
|
||||||
|
if(hRight)
|
||||||
|
updateAltarSlot(hRight);
|
||||||
|
deal->block(calcExpAltarForHero() == 0);
|
||||||
|
updateControls();
|
||||||
|
updateSubtitlesForSelected();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSide)
|
||||||
|
{
|
||||||
|
if(hCurSide == newSlot)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto * oppositeSlot = &hLeft;
|
||||||
|
auto oppositePanel = leftTradePanel;
|
||||||
|
CTradeBase::onSlotClickPressed(newSlot, hCurSide);
|
||||||
|
if(hCurSide == hLeft)
|
||||||
|
{
|
||||||
|
oppositeSlot = &hRight;
|
||||||
|
oppositePanel = rightTradePanel;
|
||||||
|
}
|
||||||
|
std::shared_ptr<CTradeableItem> oppositeNewSlot;
|
||||||
|
for(const auto & slot : oppositePanel->slots)
|
||||||
|
if(slot->serial == newSlot->serial)
|
||||||
|
{
|
||||||
|
oppositeNewSlot = slot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
assert(oppositeNewSlot);
|
||||||
|
CTradeBase::onSlotClickPressed(oppositeNewSlot, *oppositeSlot);
|
||||||
|
updateControls();
|
||||||
|
updateSubtitlesForSelected();
|
||||||
|
redraw();
|
||||||
|
}
|
37
client/widgets/markets/CAltarCreatures.h
Normal file
37
client/widgets/markets/CAltarCreatures.h
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
/*
|
||||||
|
* CAltarCreatures.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 "CTradeBase.h"
|
||||||
|
|
||||||
|
class CAltarCreatures : public CExperienceAltar, public CCreaturesSelling
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CAltarCreatures(const IMarket * market, const CGHeroInstance * hero);
|
||||||
|
void updateSlots();
|
||||||
|
void deselect() override;
|
||||||
|
TExpType calcExpAltarForHero() override;
|
||||||
|
void makeDeal() override;
|
||||||
|
void sacrificeAll() override;
|
||||||
|
void updateAltarSlot(std::shared_ptr<CTradeableItem> slot);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<CButton> maxUnits;
|
||||||
|
std::vector<int> unitsOnAltar;
|
||||||
|
std::vector<int> expPerUnit;
|
||||||
|
std::shared_ptr<CLabel> lSubtitle;
|
||||||
|
std::shared_ptr<CLabel> rSubtitle;
|
||||||
|
|
||||||
|
void readExpValues();
|
||||||
|
void updateControls();
|
||||||
|
void updateSubtitlesForSelected();
|
||||||
|
void onOfferSliderMoved(int newVal);
|
||||||
|
void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSide) override;
|
||||||
|
};
|
111
client/widgets/markets/CTradeBase.cpp
Normal file
111
client/widgets/markets/CTradeBase.cpp
Normal file
@@ -0,0 +1,111 @@
|
|||||||
|
/*
|
||||||
|
* CTradeBase.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 "CTradeBase.h"
|
||||||
|
|
||||||
|
#include "../MiscWidgets.h"
|
||||||
|
|
||||||
|
#include "../../gui/CGuiHandler.h"
|
||||||
|
#include "../../widgets/Buttons.h"
|
||||||
|
#include "../../widgets/TextControls.h"
|
||||||
|
|
||||||
|
#include "../../CGameInfo.h"
|
||||||
|
|
||||||
|
#include "../../../lib/CGeneralTextHandler.h"
|
||||||
|
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
|
||||||
|
CTradeBase::CTradeBase(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
: market(market)
|
||||||
|
, hero(hero)
|
||||||
|
{
|
||||||
|
deal = std::make_shared<CButton>(Point(), AnimationPath::builtin("ALTSACR.DEF"),
|
||||||
|
CGI->generaltexth->zelp[585], std::bind(&CTradeBase::makeDeal, this));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTradeBase::removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove)
|
||||||
|
{
|
||||||
|
for(auto item : toRemove)
|
||||||
|
removeItem(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTradeBase::removeItem(std::shared_ptr<CTradeableItem> item)
|
||||||
|
{
|
||||||
|
rightTradePanel->slots.erase(std::remove(rightTradePanel->slots.begin(), rightTradePanel->slots.end(), item));
|
||||||
|
|
||||||
|
if(hRight == item)
|
||||||
|
hRight.reset();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTradeBase::getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRemove)
|
||||||
|
{
|
||||||
|
for(auto item : leftTradePanel->slots)
|
||||||
|
if(!hero->getStackCount(SlotID(item->serial)))
|
||||||
|
toRemove.insert(item);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTradeBase::deselect()
|
||||||
|
{
|
||||||
|
if(hLeft)
|
||||||
|
hLeft->selection->selectSlot(false);
|
||||||
|
if(hRight)
|
||||||
|
hRight->selection->selectSlot(false);
|
||||||
|
hLeft = hRight = nullptr;
|
||||||
|
deal->block(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CTradeBase::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot)
|
||||||
|
{
|
||||||
|
if(newSlot == hCurSlot)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(hCurSlot)
|
||||||
|
hCurSlot->selection->selectSlot(false);
|
||||||
|
hCurSlot = newSlot;
|
||||||
|
newSlot->selection->selectSlot(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CExperienceAltar::CExperienceAltar()
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
|
// Experience needed to reach next level
|
||||||
|
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
|
||||||
|
// Total experience on the Altar
|
||||||
|
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
|
||||||
|
deal->moveBy(dealButtonPos);
|
||||||
|
expToLevel = std::make_shared<CLabel>(75, 477, FONT_SMALL, ETextAlignment::CENTER);
|
||||||
|
expForHero = std::make_shared<CLabel>(75, 545, FONT_SMALL, ETextAlignment::CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
CCreaturesSelling::CCreaturesSelling()
|
||||||
|
{
|
||||||
|
assert(hero);
|
||||||
|
CreaturesPanel::slotsData slots;
|
||||||
|
for(auto slotId = SlotID(0); slotId.num < GameConstants::ARMY_SIZE; slotId++)
|
||||||
|
{
|
||||||
|
if(const auto & creature = hero->getCreature(slotId))
|
||||||
|
slots.emplace_back(std::make_tuple(creature->getId(), slotId, hero->getStackCount(slotId)));
|
||||||
|
}
|
||||||
|
leftTradePanel = std::make_shared<CreaturesPanel>([this](const std::shared_ptr<CTradeableItem> & altarSlot)
|
||||||
|
{
|
||||||
|
CTradeBase::onSlotClickPressed(altarSlot, hLeft);
|
||||||
|
}, slots);
|
||||||
|
}
|
||||||
|
|
||||||
|
bool CCreaturesSelling::slotDeletingCheck(const std::shared_ptr<CTradeableItem> & slot)
|
||||||
|
{
|
||||||
|
return hero->getStackCount(SlotID(slot->serial)) == 0 ? true : false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CCreaturesSelling::updateSubtitle()
|
||||||
|
{
|
||||||
|
for(auto & heroSlot : leftTradePanel->slots)
|
||||||
|
heroSlot->subtitle = std::to_string(this->hero->getStackCount(SlotID(heroSlot->serial)));
|
||||||
|
}
|
74
client/widgets/markets/CTradeBase.h
Normal file
74
client/widgets/markets/CTradeBase.h
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
/*
|
||||||
|
* CTradeBase.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 "TradePanels.h"
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
|
class IMarket;
|
||||||
|
class CGHeroInstance;
|
||||||
|
|
||||||
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
|
class CButton;
|
||||||
|
class CSlider;
|
||||||
|
|
||||||
|
class CTradeBase
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
const IMarket * market;
|
||||||
|
const CGHeroInstance * hero;
|
||||||
|
|
||||||
|
//all indexes: 1 = left, 0 = right
|
||||||
|
std::array<std::vector<std::shared_ptr<CTradeableItem>>, 2> items;
|
||||||
|
std::shared_ptr<TradePanelBase> leftTradePanel;
|
||||||
|
std::shared_ptr<TradePanelBase> rightTradePanel;
|
||||||
|
|
||||||
|
//highlighted items (nullptr if no highlight)
|
||||||
|
std::shared_ptr<CTradeableItem> hLeft;
|
||||||
|
std::shared_ptr<CTradeableItem> hRight;
|
||||||
|
std::shared_ptr<CButton> deal;
|
||||||
|
std::shared_ptr<CSlider> offerSlider;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<CLabel>> labels;
|
||||||
|
std::vector<std::shared_ptr<CButton>> buttons;
|
||||||
|
std::vector<std::shared_ptr<CTextBox>> texts;
|
||||||
|
|
||||||
|
CTradeBase(const IMarket * market, const CGHeroInstance * hero);
|
||||||
|
void removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove);
|
||||||
|
void removeItem(std::shared_ptr<CTradeableItem> item);
|
||||||
|
void getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRemove);
|
||||||
|
virtual void makeDeal() = 0;
|
||||||
|
virtual void deselect();
|
||||||
|
virtual void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot);
|
||||||
|
};
|
||||||
|
|
||||||
|
// Market subclasses
|
||||||
|
class CExperienceAltar : virtual public CTradeBase, virtual public CIntObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::shared_ptr<CLabel> expToLevel;
|
||||||
|
std::shared_ptr<CLabel> expForHero;
|
||||||
|
std::shared_ptr<CButton> sacrificeAllButton;
|
||||||
|
const Point dealButtonPos = Point(269, 520);
|
||||||
|
|
||||||
|
CExperienceAltar();
|
||||||
|
virtual void sacrificeAll() = 0;
|
||||||
|
virtual TExpType calcExpAltarForHero() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CCreaturesSelling : virtual public CTradeBase, virtual public CIntObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CCreaturesSelling();
|
||||||
|
bool slotDeletingCheck(const std::shared_ptr<CTradeableItem> & slot);
|
||||||
|
void updateSubtitle();
|
||||||
|
};
|
@@ -1,5 +1,5 @@
|
|||||||
/*
|
/*
|
||||||
* CTradeBase.cpp, part of VCMI engine
|
* TradePanels.cpp, part of VCMI engine
|
||||||
*
|
*
|
||||||
* Authors: listed in file AUTHORS in main folder
|
* Authors: listed in file AUTHORS in main folder
|
||||||
*
|
*
|
||||||
@@ -8,33 +8,34 @@
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CTradeBase.h"
|
#include "TradePanels.h"
|
||||||
#include "MiscWidgets.h"
|
|
||||||
|
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../MiscWidgets.h"
|
||||||
#include "../render/Canvas.h"
|
|
||||||
#include "../widgets/Buttons.h"
|
|
||||||
#include "../widgets/TextControls.h"
|
|
||||||
#include "../windows/InfoWindows.h"
|
|
||||||
|
|
||||||
#include "../CGameInfo.h"
|
#include "../../gui/CGuiHandler.h"
|
||||||
#include "../CPlayerInterface.h"
|
#include "../../render/Canvas.h"
|
||||||
|
#include "../../widgets/TextControls.h"
|
||||||
|
#include "../../windows/InfoWindows.h"
|
||||||
|
|
||||||
#include "../../CCallback.h"
|
#include "../../CGameInfo.h"
|
||||||
|
#include "../../CPlayerInterface.h"
|
||||||
|
|
||||||
#include "../../lib/CGeneralTextHandler.h"
|
#include "../../../CCallback.h"
|
||||||
#include "../../lib/mapObjects/CGHeroInstance.h"
|
|
||||||
|
#include "../../../lib/CGeneralTextHandler.h"
|
||||||
|
#include "../../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
|
||||||
CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial)
|
CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial)
|
||||||
: CIntObject(LCLICK | HOVER | SHOW_POPUP, pos)
|
: CIntObject(LCLICK | HOVER | SHOW_POPUP, pos)
|
||||||
|
, hlp(nullptr)
|
||||||
, type(EType(-1)) // set to invalid, will be corrected in setType
|
, type(EType(-1)) // set to invalid, will be corrected in setType
|
||||||
, id(ID)
|
, id(ID)
|
||||||
, serial(Serial)
|
, serial(Serial)
|
||||||
, left(Left)
|
, left(Left)
|
||||||
|
, downSelection(false)
|
||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
||||||
downSelection = false;
|
|
||||||
hlp = nullptr;
|
|
||||||
setType(Type);
|
setType(Type);
|
||||||
if(image)
|
if(image)
|
||||||
{
|
{
|
||||||
@@ -85,15 +86,15 @@ AnimationPath CTradeableItem::getFilename()
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
return AnimationPath::builtin("RESOURCE");
|
return AnimationPath::builtin("RESOURCE");
|
||||||
case PLAYER:
|
case EType::PLAYER:
|
||||||
return AnimationPath::builtin("CREST58");
|
return AnimationPath::builtin("CREST58");
|
||||||
case ARTIFACT_TYPE:
|
case EType::ARTIFACT_TYPE:
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case EType::ARTIFACT_PLACEHOLDER:
|
||||||
case ARTIFACT_INSTANCE:
|
case EType::ARTIFACT_INSTANCE:
|
||||||
return AnimationPath::builtin("artifact");
|
return AnimationPath::builtin("artifact");
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
return AnimationPath::builtin("TWCRPORT");
|
return AnimationPath::builtin("TWCRPORT");
|
||||||
default:
|
default:
|
||||||
return {};
|
return {};
|
||||||
@@ -107,14 +108,14 @@ int CTradeableItem::getIndex()
|
|||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
case PLAYER:
|
case EType::PLAYER:
|
||||||
return id;
|
return id;
|
||||||
case ARTIFACT_TYPE:
|
case EType::ARTIFACT_TYPE:
|
||||||
case ARTIFACT_INSTANCE:
|
case EType::ARTIFACT_INSTANCE:
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case EType::ARTIFACT_PLACEHOLDER:
|
||||||
return CGI->artifacts()->getByIndex(id)->getIconIndex();
|
return CGI->artifacts()->getByIndex(id)->getIconIndex();
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
return CGI->creatures()->getByIndex(id)->getIconIndex();
|
return CGI->creatures()->getByIndex(id)->getIconIndex();
|
||||||
default:
|
default:
|
||||||
return -1;
|
return -1;
|
||||||
@@ -126,26 +127,26 @@ void CTradeableItem::showAll(Canvas & to)
|
|||||||
Point posToBitmap;
|
Point posToBitmap;
|
||||||
Point posToSubCenter;
|
Point posToSubCenter;
|
||||||
|
|
||||||
switch (type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
posToBitmap = Point(19, 9);
|
posToBitmap = Point(19, 9);
|
||||||
posToSubCenter = Point(35, 57);
|
posToSubCenter = Point(35, 57);
|
||||||
break;
|
break;
|
||||||
case CREATURE_PLACEHOLDER:
|
case EType::CREATURE_PLACEHOLDER:
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
posToSubCenter = Point(29, 77);
|
posToSubCenter = Point(29, 77);
|
||||||
break;
|
break;
|
||||||
case PLAYER:
|
case EType::PLAYER:
|
||||||
posToSubCenter = Point(31, 77);
|
posToSubCenter = Point(31, 77);
|
||||||
break;
|
break;
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case EType::ARTIFACT_PLACEHOLDER:
|
||||||
case ARTIFACT_INSTANCE:
|
case EType::ARTIFACT_INSTANCE:
|
||||||
posToSubCenter = Point(22, 51);
|
posToSubCenter = Point(22, 51);
|
||||||
if (downSelection)
|
if (downSelection)
|
||||||
posToSubCenter.y += 8;
|
posToSubCenter.y += 8;
|
||||||
break;
|
break;
|
||||||
case ARTIFACT_TYPE:
|
case EType::ARTIFACT_TYPE:
|
||||||
posToSubCenter = Point(35, 57);
|
posToSubCenter = Point(35, 57);
|
||||||
posToBitmap = Point(13, 0);
|
posToBitmap = Point(13, 0);
|
||||||
break;
|
break;
|
||||||
@@ -191,11 +192,11 @@ void CTradeableItem::hover(bool on)
|
|||||||
|
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
case CREATURE_PLACEHOLDER:
|
case EType::CREATURE_PLACEHOLDER:
|
||||||
GH.statusbar()->write(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->getNamePluralTranslated()));
|
GH.statusbar()->write(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->getNamePluralTranslated()));
|
||||||
break;
|
break;
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case EType::ARTIFACT_PLACEHOLDER:
|
||||||
if(id < 0)
|
if(id < 0)
|
||||||
GH.statusbar()->write(CGI->generaltexth->zelp[582].first);
|
GH.statusbar()->write(CGI->generaltexth->zelp[582].first);
|
||||||
else
|
else
|
||||||
@@ -208,11 +209,11 @@ void CTradeableItem::showPopupWindow(const Point & cursorPosition)
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
case CREATURE_PLACEHOLDER:
|
case EType::CREATURE_PLACEHOLDER:
|
||||||
break;
|
break;
|
||||||
case ARTIFACT_TYPE:
|
case EType::ARTIFACT_TYPE:
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case EType::ARTIFACT_PLACEHOLDER:
|
||||||
//TODO: it's would be better for market to contain actual CArtifactInstance and not just ids of certain artifact type so we can use getEffectiveDescription.
|
//TODO: it's would be better for market to contain actual CArtifactInstance and not just ids of certain artifact type so we can use getEffectiveDescription.
|
||||||
if (id >= 0)
|
if (id >= 0)
|
||||||
CRClickPopup::createAndPush(CGI->artifacts()->getByIndex(id)->getDescriptionTranslated());
|
CRClickPopup::createAndPush(CGI->artifacts()->getByIndex(id)->getDescriptionTranslated());
|
||||||
@@ -224,17 +225,17 @@ std::string CTradeableItem::getName(int number) const
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case PLAYER:
|
case EType::PLAYER:
|
||||||
return CGI->generaltexth->capColors[id];
|
return CGI->generaltexth->capColors[id];
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
return CGI->generaltexth->restypes[id];
|
return CGI->generaltexth->restypes[id];
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
if (number == 1)
|
if (number == 1)
|
||||||
return CGI->creh->objects[id]->getNameSingularTranslated();
|
return CGI->creh->objects[id]->getNameSingularTranslated();
|
||||||
else
|
else
|
||||||
return CGI->creh->objects[id]->getNamePluralTranslated();
|
return CGI->creh->objects[id]->getNamePluralTranslated();
|
||||||
case ARTIFACT_TYPE:
|
case EType::ARTIFACT_TYPE:
|
||||||
case ARTIFACT_INSTANCE:
|
case EType::ARTIFACT_INSTANCE:
|
||||||
return CGI->artifacts()->getByIndex(id)->getNameTranslated();
|
return CGI->artifacts()->getByIndex(id)->getNameTranslated();
|
||||||
}
|
}
|
||||||
logGlobal->error("Invalid trade item type: %d", (int)type);
|
logGlobal->error("Invalid trade item type: %d", (int)type);
|
||||||
@@ -245,8 +246,8 @@ const CArtifactInstance * CTradeableItem::getArtInstance() const
|
|||||||
{
|
{
|
||||||
switch(type)
|
switch(type)
|
||||||
{
|
{
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case EType::ARTIFACT_PLACEHOLDER:
|
||||||
case ARTIFACT_INSTANCE:
|
case EType::ARTIFACT_INSTANCE:
|
||||||
return hlp;
|
return hlp;
|
||||||
default:
|
default:
|
||||||
return nullptr;
|
return nullptr;
|
||||||
@@ -255,46 +256,49 @@ const CArtifactInstance * CTradeableItem::getArtInstance() const
|
|||||||
|
|
||||||
void CTradeableItem::setArtInstance(const CArtifactInstance * art)
|
void CTradeableItem::setArtInstance(const CArtifactInstance * art)
|
||||||
{
|
{
|
||||||
assert(type == ARTIFACT_PLACEHOLDER || type == ARTIFACT_INSTANCE);
|
assert(type == EType::ARTIFACT_PLACEHOLDER || type == EType::ARTIFACT_INSTANCE);
|
||||||
hlp = art;
|
hlp = art;
|
||||||
if(art)
|
if(art)
|
||||||
setID(art->artType->getId());
|
setID(art->getTypeId());
|
||||||
else
|
else
|
||||||
setID(-1);
|
setID(-1);
|
||||||
}
|
}
|
||||||
|
|
||||||
void STradePanel::updateSlots()
|
void TradePanelBase::updateSlots()
|
||||||
{
|
{
|
||||||
if(updateSlotsCallback)
|
if(updateSlotsCallback)
|
||||||
updateSlotsCallback();
|
updateSlotsCallback();
|
||||||
}
|
}
|
||||||
|
|
||||||
void STradePanel::deselect()
|
void TradePanelBase::deselect()
|
||||||
{
|
{
|
||||||
for(auto & slot : slots)
|
for(const auto & slot : slots)
|
||||||
slot->selection->selectSlot(false);
|
slot->selection->selectSlot(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void STradePanel::clearSubtitles()
|
void TradePanelBase::clearSubtitles()
|
||||||
{
|
{
|
||||||
for(auto & slot : slots)
|
for(const auto & slot : slots)
|
||||||
slot->subtitle.clear();
|
slot->subtitle.clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
void STradePanel::updateOffer(CTradeableItem & slot, int cost, int qty)
|
void TradePanelBase::updateOffer(CTradeableItem & slot, int cost, int qty)
|
||||||
{
|
{
|
||||||
slot.subtitle = std::to_string(qty);
|
slot.subtitle = std::to_string(qty);
|
||||||
if(cost != 1)
|
if(cost != 1)
|
||||||
slot.subtitle += "/" + std::to_string(cost);
|
{
|
||||||
|
slot.subtitle.append("/");
|
||||||
|
slot.subtitle.append(std::to_string(cost));
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void STradePanel::deleteSlots()
|
void TradePanelBase::deleteSlots()
|
||||||
{
|
{
|
||||||
if(deleteSlotsCheck)
|
if(deleteSlotsCheck)
|
||||||
slots.erase(std::remove_if(slots.begin(), slots.end(), deleteSlotsCheck), slots.end());
|
slots.erase(std::remove_if(slots.begin(), slots.end(), deleteSlotsCheck), slots.end());
|
||||||
}
|
}
|
||||||
|
|
||||||
SResourcesPanel::SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles)
|
ResourcesPanel::ResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles)
|
||||||
{
|
{
|
||||||
assert(resourcesForTrade.size() == slotsPos.size());
|
assert(resourcesForTrade.size() == slotsPos.size());
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
@@ -309,8 +313,8 @@ SResourcesPanel::SResourcesPanel(CTradeableItem::ClickPressedFunctor clickPresse
|
|||||||
updateSlotsCallback = updateSubtitles;
|
updateSlotsCallback = updateSubtitles;
|
||||||
}
|
}
|
||||||
|
|
||||||
SArtifactsPanel::SArtifactsPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles,
|
ArtifactsPanel::ArtifactsPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles,
|
||||||
std::vector<TradeItemBuy> & arts)
|
const std::vector<TradeItemBuy> & arts)
|
||||||
{
|
{
|
||||||
assert(slotsForTrade == slotsPos.size());
|
assert(slotsForTrade == slotsPos.size());
|
||||||
assert(slotsForTrade == arts.size());
|
assert(slotsForTrade == arts.size());
|
||||||
@@ -330,9 +334,9 @@ SArtifactsPanel::SArtifactsPanel(CTradeableItem::ClickPressedFunctor clickPresse
|
|||||||
updateSlotsCallback = updateSubtitles;
|
updateSlotsCallback = updateSubtitles;
|
||||||
}
|
}
|
||||||
|
|
||||||
SPlayersPanel::SPlayersPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback)
|
PlayersPanel::PlayersPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback)
|
||||||
{
|
{
|
||||||
assert(PlayerColor::PLAYER_LIMIT_I <= slotsPos.size());
|
assert(PlayerColor::PLAYER_LIMIT_I <= slotsPos.size() + 1);
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
std::vector<PlayerColor> players;
|
std::vector<PlayerColor> players;
|
||||||
@@ -349,37 +353,36 @@ SPlayersPanel::SPlayersPanel(CTradeableItem::ClickPressedFunctor clickPressedCal
|
|||||||
slot = std::make_shared<CTradeableItem>(slotsPos[slotNum], EType::PLAYER, players[slotNum].num, false, slotNum);
|
slot = std::make_shared<CTradeableItem>(slotsPos[slotNum], EType::PLAYER, players[slotNum].num, false, slotNum);
|
||||||
slot->clickPressedCallback = clickPressedCallback;
|
slot->clickPressedCallback = clickPressedCallback;
|
||||||
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slotNum], slot->pos.dimensions()), Point(1, 1), selectionWidth);
|
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slotNum], slot->pos.dimensions()), Point(1, 1), selectionWidth);
|
||||||
slot->subtitle = CGI->generaltexth->capColors[players[slotNum++].num];
|
slot->subtitle = CGI->generaltexth->capColors[players[slotNum].num];
|
||||||
|
slotNum++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SCreaturesPanel::SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, slotsData & initialSlots)
|
CreaturesPanel::CreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, const slotsData & initialSlots)
|
||||||
{
|
{
|
||||||
assert(initialSlots.size() <= GameConstants::ARMY_SIZE);
|
assert(initialSlots.size() <= GameConstants::ARMY_SIZE);
|
||||||
assert(slotsPos.size() <= GameConstants::ARMY_SIZE);
|
assert(slotsPos.size() <= GameConstants::ARMY_SIZE);
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
for(const auto & slotData : initialSlots)
|
for(const auto & [creatureId, slotId, creaturesNum] : initialSlots)
|
||||||
{
|
{
|
||||||
auto slotId = std::get<1>(slotData);
|
|
||||||
auto creaturesNum = std::get<2>(slotData);
|
|
||||||
auto slot = slots.emplace_back(std::make_shared<CTradeableItem>(slotsPos[slotId.num],
|
auto slot = slots.emplace_back(std::make_shared<CTradeableItem>(slotsPos[slotId.num],
|
||||||
creaturesNum == 0 ? EType::CREATURE_PLACEHOLDER : EType::CREATURE, std::get<0>(slotData).num, true, slotId));
|
creaturesNum == 0 ? EType::CREATURE_PLACEHOLDER : EType::CREATURE, creatureId.num, true, slotId));
|
||||||
slot->clickPressedCallback = clickPressedCallback;
|
slot->clickPressedCallback = clickPressedCallback;
|
||||||
if(creaturesNum != 0)
|
if(creaturesNum != 0)
|
||||||
slot->subtitle = std::to_string(std::get<2>(slotData));
|
slot->subtitle = std::to_string(creaturesNum);
|
||||||
slot->pos.w = 58; slot->pos.h = 64;
|
slot->pos.w = 58; slot->pos.h = 64;
|
||||||
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slotId.num], slot->pos.dimensions()), Point(1, 1), selectionWidth);
|
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slotId.num], slot->pos.dimensions()), Point(1, 1), selectionWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
SCreaturesPanel::SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback,
|
CreaturesPanel::CreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback,
|
||||||
std::vector<std::shared_ptr<CTradeableItem>> & stsSlots, bool emptySlots)
|
const std::vector<std::shared_ptr<CTradeableItem>> & srcSlots, bool emptySlots)
|
||||||
{
|
{
|
||||||
assert(slots.size() <= GameConstants::ARMY_SIZE);
|
assert(slots.size() <= GameConstants::ARMY_SIZE);
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
for(const auto & srcSlot : stsSlots)
|
for(const auto & srcSlot : srcSlots)
|
||||||
{
|
{
|
||||||
auto slot = slots.emplace_back(std::make_shared<CTradeableItem>(slotsPos[srcSlot->serial],
|
auto slot = slots.emplace_back(std::make_shared<CTradeableItem>(slotsPos[srcSlot->serial],
|
||||||
emptySlots ? EType::CREATURE_PLACEHOLDER : EType::CREATURE, srcSlot->id, true, srcSlot->serial));
|
emptySlots ? EType::CREATURE_PLACEHOLDER : EType::CREATURE, srcSlot->id, true, srcSlot->serial));
|
||||||
@@ -389,92 +392,3 @@ SCreaturesPanel::SCreaturesPanel(CTradeableItem::ClickPressedFunctor clickPresse
|
|||||||
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slot->serial], slot->pos.dimensions()), Point(1, 1), selectionWidth);
|
slot->selection = std::make_unique<SelectableSlot>(Rect(slotsPos[slot->serial], slot->pos.dimensions()), Point(1, 1), selectionWidth);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CTradeBase::CTradeBase(const IMarket * market, const CGHeroInstance * hero)
|
|
||||||
: market(market)
|
|
||||||
, hero(hero)
|
|
||||||
{
|
|
||||||
deal = std::make_shared<CButton>(Point(), AnimationPath::builtin("ALTSACR.DEF"),
|
|
||||||
CGI->generaltexth->zelp[585], std::bind(&CTradeBase::makeDeal, this));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTradeBase::removeItems(const std::set<std::shared_ptr<CTradeableItem>> & toRemove)
|
|
||||||
{
|
|
||||||
for(auto item : toRemove)
|
|
||||||
removeItem(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTradeBase::removeItem(std::shared_ptr<CTradeableItem> item)
|
|
||||||
{
|
|
||||||
rightTradePanel->slots.erase(std::remove(rightTradePanel->slots.begin(), rightTradePanel->slots.end(), item));
|
|
||||||
|
|
||||||
if(hRight == item)
|
|
||||||
hRight.reset();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTradeBase::getEmptySlots(std::set<std::shared_ptr<CTradeableItem>> & toRemove)
|
|
||||||
{
|
|
||||||
for(auto item : leftTradePanel->slots)
|
|
||||||
if(!hero->getStackCount(SlotID(item->serial)))
|
|
||||||
toRemove.insert(item);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTradeBase::deselect()
|
|
||||||
{
|
|
||||||
if(hLeft)
|
|
||||||
hLeft->selection->selectSlot(false);
|
|
||||||
if(hRight)
|
|
||||||
hRight->selection->selectSlot(false);
|
|
||||||
hLeft = hRight = nullptr;
|
|
||||||
deal->block(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CTradeBase::onSlotClickPressed(std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot)
|
|
||||||
{
|
|
||||||
if(newSlot == hCurSlot)
|
|
||||||
return;
|
|
||||||
|
|
||||||
if(hCurSlot)
|
|
||||||
hCurSlot->selection->selectSlot(false);
|
|
||||||
hCurSlot = newSlot;
|
|
||||||
newSlot->selection->selectSlot(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
CExpAltar::CExpAltar()
|
|
||||||
{
|
|
||||||
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
|
|
||||||
|
|
||||||
// Experience needed to reach next level
|
|
||||||
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[475], Rect(15, 415, 125, 50), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
|
|
||||||
// Total experience on the Altar
|
|
||||||
texts.emplace_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
|
|
||||||
deal->moveBy(dealButtonPos);
|
|
||||||
expToLevel = std::make_shared<CLabel>(75, 477, FONT_SMALL, ETextAlignment::CENTER);
|
|
||||||
expForHero = std::make_shared<CLabel>(75, 545, FONT_SMALL, ETextAlignment::CENTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
CCreaturesSelling::CCreaturesSelling()
|
|
||||||
{
|
|
||||||
assert(hero);
|
|
||||||
SCreaturesPanel::slotsData slots;
|
|
||||||
for(auto slotId = SlotID(0); slotId.num < GameConstants::ARMY_SIZE; slotId++)
|
|
||||||
{
|
|
||||||
if(const auto & creature = hero->getCreature(slotId))
|
|
||||||
slots.emplace_back(std::make_tuple(creature->getId(), slotId, hero->getStackCount(slotId)));
|
|
||||||
}
|
|
||||||
leftTradePanel = std::make_shared<SCreaturesPanel>([this](std::shared_ptr<CTradeableItem> altarSlot) -> void
|
|
||||||
{
|
|
||||||
onSlotClickPressed(altarSlot, hLeft);
|
|
||||||
}, slots);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CCreaturesSelling::slotDeletingCheck(std::shared_ptr<CTradeableItem> & slot)
|
|
||||||
{
|
|
||||||
return hero->getStackCount(SlotID(slot->serial)) == 0 ? true : false;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCreaturesSelling::updateSubtitle()
|
|
||||||
{
|
|
||||||
for(auto & heroSlot : leftTradePanel->slots)
|
|
||||||
heroSlot->subtitle = std::to_string(this->hero->getStackCount(SlotID(heroSlot->serial)));
|
|
||||||
}
|
|
140
client/widgets/markets/TradePanels.h
Normal file
140
client/widgets/markets/TradePanels.h
Normal file
@@ -0,0 +1,140 @@
|
|||||||
|
/*
|
||||||
|
* TradePanels.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 "../Images.h"
|
||||||
|
|
||||||
|
#include "../../../lib/networkPacks/TradeItem.h"
|
||||||
|
|
||||||
|
class CTextBox;
|
||||||
|
class SelectableSlot;
|
||||||
|
|
||||||
|
enum class EType
|
||||||
|
{
|
||||||
|
RESOURCE, PLAYER, ARTIFACT_TYPE, CREATURE, CREATURE_PLACEHOLDER, ARTIFACT_PLACEHOLDER, ARTIFACT_INSTANCE
|
||||||
|
};
|
||||||
|
|
||||||
|
class CTradeableItem : public CIntObject, public std::enable_shared_from_this<CTradeableItem>
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::shared_ptr<CAnimImage> image;
|
||||||
|
AnimationPath getFilename();
|
||||||
|
int getIndex();
|
||||||
|
using ClickPressedFunctor = std::function<void(const std::shared_ptr<CTradeableItem>&)>;
|
||||||
|
|
||||||
|
const CArtifactInstance * hlp; //holds ptr to artifact instance id type artifact
|
||||||
|
EType type;
|
||||||
|
int id;
|
||||||
|
const int serial;
|
||||||
|
const bool left;
|
||||||
|
std::string subtitle;
|
||||||
|
ClickPressedFunctor clickPressedCallback;
|
||||||
|
|
||||||
|
void setType(EType newType);
|
||||||
|
void setID(int newID);
|
||||||
|
|
||||||
|
const CArtifactInstance * getArtInstance() const;
|
||||||
|
void setArtInstance(const CArtifactInstance * art);
|
||||||
|
|
||||||
|
std::unique_ptr<SelectableSlot> selection;
|
||||||
|
bool downSelection;
|
||||||
|
|
||||||
|
void showAllAt(const Point & dstPos, const std::string & customSub, Canvas & to);
|
||||||
|
|
||||||
|
void showPopupWindow(const Point & cursorPosition) override;
|
||||||
|
void hover(bool on) override;
|
||||||
|
void showAll(Canvas & to) override;
|
||||||
|
void clickPressed(const Point & cursorPosition) override;
|
||||||
|
std::string getName(int number = -1) const;
|
||||||
|
CTradeableItem(Point pos, EType Type, int ID, bool Left, int Serial);
|
||||||
|
};
|
||||||
|
|
||||||
|
class TradePanelBase : public CIntObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
using UpdateSlotsFunctor = std::function<void()>;
|
||||||
|
using DeleteSlotsCheck = std::function<bool(const std::shared_ptr<CTradeableItem>&)>;
|
||||||
|
|
||||||
|
std::vector<std::shared_ptr<CTradeableItem>> slots;
|
||||||
|
UpdateSlotsFunctor updateSlotsCallback;
|
||||||
|
DeleteSlotsCheck deleteSlotsCheck;
|
||||||
|
std::shared_ptr<CTradeableItem> selected;
|
||||||
|
const int selectionWidth = 2;
|
||||||
|
|
||||||
|
virtual void updateSlots();
|
||||||
|
virtual void deselect();
|
||||||
|
virtual void clearSubtitles();
|
||||||
|
void updateOffer(CTradeableItem & slot, int, int);
|
||||||
|
void deleteSlots();
|
||||||
|
};
|
||||||
|
|
||||||
|
class ResourcesPanel : public TradePanelBase
|
||||||
|
{
|
||||||
|
const std::vector<GameResID> resourcesForTrade =
|
||||||
|
{
|
||||||
|
GameResID::WOOD, GameResID::MERCURY, GameResID::ORE,
|
||||||
|
GameResID::SULFUR, GameResID::CRYSTAL, GameResID::GEMS,
|
||||||
|
GameResID::GOLD
|
||||||
|
};
|
||||||
|
const std::vector<Point> slotsPos =
|
||||||
|
{
|
||||||
|
Point(0, 0), Point(83, 0), Point(166, 0),
|
||||||
|
Point(0, 79), Point(83, 79), Point(166, 79),
|
||||||
|
Point(83, 158)
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
ResourcesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles);
|
||||||
|
};
|
||||||
|
|
||||||
|
class ArtifactsPanel : public TradePanelBase
|
||||||
|
{
|
||||||
|
const std::vector<Point> slotsPos =
|
||||||
|
{
|
||||||
|
Point(0, 0), Point(83, 0), Point(166, 0),
|
||||||
|
Point(0, 79), Point(83, 79), Point(166, 79),
|
||||||
|
Point(83, 158)
|
||||||
|
};
|
||||||
|
const size_t slotsForTrade = 7;
|
||||||
|
|
||||||
|
public:
|
||||||
|
ArtifactsPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, UpdateSlotsFunctor updateSubtitles,
|
||||||
|
const std::vector<TradeItemBuy> & arts);
|
||||||
|
};
|
||||||
|
|
||||||
|
class PlayersPanel : public TradePanelBase
|
||||||
|
{
|
||||||
|
const std::vector<Point> slotsPos =
|
||||||
|
{
|
||||||
|
Point(0, 0), Point(83, 0), Point(166, 0),
|
||||||
|
Point(0, 118), Point(83, 118), Point(166, 118),
|
||||||
|
Point(83, 236)
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
explicit PlayersPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CreaturesPanel : public TradePanelBase
|
||||||
|
{
|
||||||
|
const std::vector<Point> slotsPos =
|
||||||
|
{
|
||||||
|
Point(0, 0), Point(83, 0), Point(166, 0),
|
||||||
|
Point(0, 98), Point(83, 98), Point(166, 98),
|
||||||
|
Point(83, 196)
|
||||||
|
};
|
||||||
|
|
||||||
|
public:
|
||||||
|
using slotsData = std::vector<std::tuple<CreatureID, SlotID, int>>;
|
||||||
|
|
||||||
|
CreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback, const slotsData & initialSlots);
|
||||||
|
CreaturesPanel(CTradeableItem::ClickPressedFunctor clickPressedCallback,
|
||||||
|
const std::vector<std::shared_ptr<CTradeableItem>> & srcSlots, bool emptySlots = true);
|
||||||
|
};
|
@@ -9,7 +9,8 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../widgets/CAltar.h"
|
#include "../widgets/markets/CAltarArtifacts.h"
|
||||||
|
#include "../widgets/markets/CAltarCreatures.h"
|
||||||
#include "../widgets/CWindowWithArtifacts.h"
|
#include "../widgets/CWindowWithArtifacts.h"
|
||||||
#include "CWindowObject.h"
|
#include "CWindowObject.h"
|
||||||
|
|
||||||
@@ -28,7 +29,7 @@ public:
|
|||||||
|
|
||||||
private:
|
private:
|
||||||
const CGHeroInstance * hero;
|
const CGHeroInstance * hero;
|
||||||
std::shared_ptr<CExpAltar> altar;
|
std::shared_ptr<CExperienceAltar> altar;
|
||||||
std::shared_ptr<CButton> changeModeButton;
|
std::shared_ptr<CButton> changeModeButton;
|
||||||
std::shared_ptr<CButton> quitButton;
|
std::shared_ptr<CButton> quitButton;
|
||||||
std::function<void()> windowClosedCallback;
|
std::function<void()> windowClosedCallback;
|
||||||
|
@@ -47,24 +47,24 @@ void CTradeWindow::initTypes()
|
|||||||
switch(mode)
|
switch(mode)
|
||||||
{
|
{
|
||||||
case EMarketMode::RESOURCE_RESOURCE:
|
case EMarketMode::RESOURCE_RESOURCE:
|
||||||
itemsType[1] = RESOURCE;
|
itemsType[1] = EType::RESOURCE;
|
||||||
itemsType[0] = RESOURCE;
|
itemsType[0] = EType::RESOURCE;
|
||||||
break;
|
break;
|
||||||
case EMarketMode::RESOURCE_PLAYER:
|
case EMarketMode::RESOURCE_PLAYER:
|
||||||
itemsType[1] = RESOURCE;
|
itemsType[1] = EType::RESOURCE;
|
||||||
itemsType[0] = PLAYER;
|
itemsType[0] = EType::PLAYER;
|
||||||
break;
|
break;
|
||||||
case EMarketMode::CREATURE_RESOURCE:
|
case EMarketMode::CREATURE_RESOURCE:
|
||||||
itemsType[1] = CREATURE;
|
itemsType[1] = EType::CREATURE;
|
||||||
itemsType[0] = RESOURCE;
|
itemsType[0] = EType::RESOURCE;
|
||||||
break;
|
break;
|
||||||
case EMarketMode::RESOURCE_ARTIFACT:
|
case EMarketMode::RESOURCE_ARTIFACT:
|
||||||
itemsType[1] = RESOURCE;
|
itemsType[1] = EType::RESOURCE;
|
||||||
itemsType[0] = ARTIFACT_TYPE;
|
itemsType[0] = EType::ARTIFACT_TYPE;
|
||||||
break;
|
break;
|
||||||
case EMarketMode::ARTIFACT_RESOURCE:
|
case EMarketMode::ARTIFACT_RESOURCE:
|
||||||
itemsType[1] = ARTIFACT_INSTANCE;
|
itemsType[1] = EType::ARTIFACT_INSTANCE;
|
||||||
itemsType[0] = RESOURCE;
|
itemsType[0] = EType::RESOURCE;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -73,7 +73,7 @@ void CTradeWindow::initItems(bool Left)
|
|||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||||
|
|
||||||
if(Left && (itemsType[1] == ARTIFACT_TYPE || itemsType[1] == ARTIFACT_INSTANCE))
|
if(Left && (itemsType[1] == EType::ARTIFACT_TYPE || itemsType[1] == EType::ARTIFACT_INSTANCE))
|
||||||
{
|
{
|
||||||
if(mode == EMarketMode::ARTIFACT_RESOURCE)
|
if(mode == EMarketMode::ARTIFACT_RESOURCE)
|
||||||
{
|
{
|
||||||
@@ -84,13 +84,13 @@ void CTradeWindow::initItems(bool Left)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
auto updRightSub = [this](EMarketMode mode) -> void
|
auto updRightSub = [this](EMarketMode marketMode)
|
||||||
{
|
{
|
||||||
if(hLeft)
|
if(hLeft)
|
||||||
for(auto & slot : rightTradePanel->slots)
|
for(const auto & slot : rightTradePanel->slots)
|
||||||
{
|
{
|
||||||
int h1, h2; //hlp variables for getting offer
|
int h1, h2; //hlp variables for getting offer
|
||||||
market->getOffer(hLeft->id, slot->id, h1, h2, mode);
|
market->getOffer(hLeft->id, slot->id, h1, h2, marketMode);
|
||||||
|
|
||||||
rightTradePanel->updateOffer(*slot, h1, h2);
|
rightTradePanel->updateOffer(*slot, h1, h2);
|
||||||
}
|
}
|
||||||
@@ -98,7 +98,7 @@ void CTradeWindow::initItems(bool Left)
|
|||||||
rightTradePanel->clearSubtitles();
|
rightTradePanel->clearSubtitles();
|
||||||
};
|
};
|
||||||
|
|
||||||
auto clickPressedTradePanel = [this](std::shared_ptr<CTradeableItem> newSlot, bool left)
|
auto clickPressedTradePanel = [this](const std::shared_ptr<CTradeableItem> & newSlot, bool left)
|
||||||
{
|
{
|
||||||
CTradeBase::onSlotClickPressed(newSlot, left ? hLeft : hRight);
|
CTradeBase::onSlotClickPressed(newSlot, left ? hLeft : hRight);
|
||||||
selectionChanged(left);
|
selectionChanged(left);
|
||||||
@@ -106,25 +106,29 @@ void CTradeWindow::initItems(bool Left)
|
|||||||
|
|
||||||
if(Left && mode == EMarketMode::CREATURE_RESOURCE)
|
if(Left && mode == EMarketMode::CREATURE_RESOURCE)
|
||||||
{
|
{
|
||||||
SCreaturesPanel::slotsData slots;
|
CreaturesPanel::slotsData slots;
|
||||||
for(auto slotId = SlotID(0); slotId.num < GameConstants::ARMY_SIZE; slotId++)
|
for(auto slotId = SlotID(0); slotId.num < GameConstants::ARMY_SIZE; slotId++)
|
||||||
{
|
{
|
||||||
if(const auto & creature = hero->getCreature(slotId))
|
if(const auto & creature = hero->getCreature(slotId))
|
||||||
slots.emplace_back(std::make_tuple(creature->getId(), slotId, hero->getStackCount(slotId)));
|
slots.emplace_back(std::make_tuple(creature->getId(), slotId, hero->getStackCount(slotId)));
|
||||||
}
|
}
|
||||||
leftTradePanel = std::make_shared<SCreaturesPanel>(std::bind(clickPressedTradePanel, _1, true), slots);
|
leftTradePanel = std::make_shared<CreaturesPanel>(std::bind(clickPressedTradePanel, _1, true), slots);
|
||||||
leftTradePanel->moveBy(Point(45, 123));
|
leftTradePanel->moveBy(Point(45, 123));
|
||||||
leftTradePanel->deleteSlotsCheck = [this](std::shared_ptr<CTradeableItem> & slot) -> bool
|
leftTradePanel->deleteSlotsCheck = [this](const std::shared_ptr<CTradeableItem> & slot)
|
||||||
{
|
{
|
||||||
return this->hero->getStackCount(SlotID(slot->serial)) == 0 ? true : false;
|
return this->hero->getStackCount(SlotID(slot->serial)) == 0 ? true : false;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if(Left && (mode == EMarketMode::RESOURCE_RESOURCE || mode == EMarketMode::RESOURCE_ARTIFACT || mode == EMarketMode::RESOURCE_PLAYER))
|
else if(Left && (mode == EMarketMode::RESOURCE_RESOURCE || mode == EMarketMode::RESOURCE_ARTIFACT || mode == EMarketMode::RESOURCE_PLAYER))
|
||||||
{
|
{
|
||||||
leftTradePanel = std::make_shared<SResourcesPanel>(std::bind(clickPressedTradePanel, _1, true),
|
leftTradePanel = std::make_shared<ResourcesPanel>(
|
||||||
[this]() -> void
|
[clickPressedTradePanel](const std::shared_ptr<CTradeableItem> & newSlot)
|
||||||
{
|
{
|
||||||
for(auto & slot : leftTradePanel->slots)
|
clickPressedTradePanel(newSlot, true);
|
||||||
|
},
|
||||||
|
[this]()
|
||||||
|
{
|
||||||
|
for(const auto & slot : leftTradePanel->slots)
|
||||||
slot->subtitle = std::to_string(LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(slot->serial)));
|
slot->subtitle = std::to_string(LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(slot->serial)));
|
||||||
});
|
});
|
||||||
leftTradePanel->moveBy(Point(39, 182));
|
leftTradePanel->moveBy(Point(39, 182));
|
||||||
@@ -132,8 +136,12 @@ void CTradeWindow::initItems(bool Left)
|
|||||||
}
|
}
|
||||||
else if(!Left && mode == EMarketMode::RESOURCE_RESOURCE)
|
else if(!Left && mode == EMarketMode::RESOURCE_RESOURCE)
|
||||||
{
|
{
|
||||||
rightTradePanel = std::make_shared<SResourcesPanel>(std::bind(clickPressedTradePanel, _1, false),
|
rightTradePanel = std::make_shared<ResourcesPanel>(
|
||||||
[this, updRightSub]() -> void
|
[clickPressedTradePanel](const std::shared_ptr<CTradeableItem> & newSlot)
|
||||||
|
{
|
||||||
|
clickPressedTradePanel(newSlot, false);
|
||||||
|
},
|
||||||
|
[this, updRightSub]()
|
||||||
{
|
{
|
||||||
updRightSub(EMarketMode::RESOURCE_RESOURCE);
|
updRightSub(EMarketMode::RESOURCE_RESOURCE);
|
||||||
if(hLeft)
|
if(hLeft)
|
||||||
@@ -143,23 +151,23 @@ void CTradeWindow::initItems(bool Left)
|
|||||||
}
|
}
|
||||||
else if(!Left && (mode == EMarketMode::ARTIFACT_RESOURCE || mode == EMarketMode::CREATURE_RESOURCE))
|
else if(!Left && (mode == EMarketMode::ARTIFACT_RESOURCE || mode == EMarketMode::CREATURE_RESOURCE))
|
||||||
{
|
{
|
||||||
rightTradePanel = std::make_shared<SResourcesPanel>(std::bind(clickPressedTradePanel, _1, false),
|
rightTradePanel = std::make_shared<ResourcesPanel>(std::bind(clickPressedTradePanel, _1, false),
|
||||||
std::bind(updRightSub, EMarketMode::ARTIFACT_RESOURCE));
|
std::bind(updRightSub, EMarketMode::ARTIFACT_RESOURCE));
|
||||||
rightTradePanel->moveBy(Point(327, 181));
|
rightTradePanel->moveBy(Point(327, 181));
|
||||||
}
|
}
|
||||||
else if(!Left && mode == EMarketMode::RESOURCE_ARTIFACT)
|
else if(!Left && mode == EMarketMode::RESOURCE_ARTIFACT)
|
||||||
{
|
{
|
||||||
rightTradePanel = std::make_shared<SArtifactsPanel>(std::bind(clickPressedTradePanel, _1, false),
|
rightTradePanel = std::make_shared<ArtifactsPanel>(std::bind(clickPressedTradePanel, _1, false),
|
||||||
std::bind(updRightSub, EMarketMode::RESOURCE_ARTIFACT), market->availableItemsIds(mode));
|
std::bind(updRightSub, EMarketMode::RESOURCE_ARTIFACT), market->availableItemsIds(mode));
|
||||||
rightTradePanel->moveBy(Point(327, 181));
|
rightTradePanel->moveBy(Point(327, 181));
|
||||||
rightTradePanel->deleteSlotsCheck = [this](std::shared_ptr<CTradeableItem> & slot) -> bool
|
rightTradePanel->deleteSlotsCheck = [this](const std::shared_ptr<CTradeableItem> & slot)
|
||||||
{
|
{
|
||||||
return vstd::contains(market->availableItemsIds(EMarketMode::RESOURCE_ARTIFACT), ArtifactID(slot->id)) ? false : true;
|
return vstd::contains(market->availableItemsIds(EMarketMode::RESOURCE_ARTIFACT), ArtifactID(slot->id)) ? false : true;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else if(!Left && mode == EMarketMode::RESOURCE_PLAYER)
|
else if(!Left && mode == EMarketMode::RESOURCE_PLAYER)
|
||||||
{
|
{
|
||||||
rightTradePanel = std::make_shared<SPlayersPanel>(std::bind(clickPressedTradePanel, _1, false));
|
rightTradePanel = std::make_shared<PlayersPanel>(std::bind(clickPressedTradePanel, _1, false));
|
||||||
rightTradePanel->moveBy(Point(333, 83));
|
rightTradePanel->moveBy(Point(333, 83));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -167,7 +175,7 @@ void CTradeWindow::initItems(bool Left)
|
|||||||
|
|
||||||
void CTradeWindow::initSubs(bool Left)
|
void CTradeWindow::initSubs(bool Left)
|
||||||
{
|
{
|
||||||
if(itemsType[Left] == RESOURCE || itemsType[Left] == ARTIFACT_TYPE)
|
if(itemsType[Left] == EType::RESOURCE || itemsType[Left] == EType::ARTIFACT_TYPE)
|
||||||
{
|
{
|
||||||
if(Left)
|
if(Left)
|
||||||
leftTradePanel->updateSlots();
|
leftTradePanel->updateSlots();
|
||||||
@@ -464,9 +472,9 @@ void CMarketplaceWindow::selectionChanged(bool side)
|
|||||||
if(slider)
|
if(slider)
|
||||||
{
|
{
|
||||||
int newAmount = -1;
|
int newAmount = -1;
|
||||||
if(itemsType[1] == RESOURCE)
|
if(itemsType[1] == EType::RESOURCE)
|
||||||
newAmount = LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(soldItemId));
|
newAmount = LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(soldItemId));
|
||||||
else if(itemsType[1] == CREATURE)
|
else if(itemsType[1] == EType::CREATURE)
|
||||||
newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->stacksCount() == 1 && hero->needsLastStack());
|
newAmount = hero->getStackCount(SlotID(hLeft->serial)) - (hero->stacksCount() == 1 && hero->needsLastStack());
|
||||||
else
|
else
|
||||||
assert(0);
|
assert(0);
|
||||||
@@ -476,7 +484,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
|
|||||||
max->block(false);
|
max->block(false);
|
||||||
deal->block(false);
|
deal->block(false);
|
||||||
}
|
}
|
||||||
else if(itemsType[1] == RESOURCE) //buying -> check if we can afford transaction
|
else if(itemsType[1] == EType::RESOURCE) //buying -> check if we can afford transaction
|
||||||
{
|
{
|
||||||
deal->block(LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(soldItemId)) < r1);
|
deal->block(LOCPLINT->cb->getResourceAmount(static_cast<EGameResID>(soldItemId)) < r1);
|
||||||
}
|
}
|
||||||
@@ -494,7 +502,7 @@ void CMarketplaceWindow::selectionChanged(bool side)
|
|||||||
deal->block(true);
|
deal->block(true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(side && itemsType[0] != PLAYER) //items[1] selection changed, recalculate offers
|
if(side && itemsType[0] != EType::PLAYER) //items[1] selection changed, recalculate offers
|
||||||
initSubs(false);
|
initSubs(false);
|
||||||
|
|
||||||
updateTraderText();
|
updateTraderText();
|
||||||
@@ -549,8 +557,8 @@ std::string CMarketplaceWindow::updateSlotSubtitle(bool Left) const
|
|||||||
{
|
{
|
||||||
switch(itemsType[1])
|
switch(itemsType[1])
|
||||||
{
|
{
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
{
|
{
|
||||||
int val = slider
|
int val = slider
|
||||||
? slider->getValue() * r1
|
? slider->getValue() * r1
|
||||||
@@ -558,7 +566,7 @@ std::string CMarketplaceWindow::updateSlotSubtitle(bool Left) const
|
|||||||
|
|
||||||
return std::to_string(val);
|
return std::to_string(val);
|
||||||
}
|
}
|
||||||
case ARTIFACT_INSTANCE:
|
case EType::ARTIFACT_INSTANCE:
|
||||||
return ((deal->isBlocked()) ? "0" : "1");
|
return ((deal->isBlocked()) ? "0" : "1");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -566,14 +574,14 @@ std::string CMarketplaceWindow::updateSlotSubtitle(bool Left) const
|
|||||||
{
|
{
|
||||||
switch(itemsType[0])
|
switch(itemsType[0])
|
||||||
{
|
{
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
if(slider)
|
if(slider)
|
||||||
return std::to_string( slider->getValue() * r2 );
|
return std::to_string( slider->getValue() * r2 );
|
||||||
else
|
else
|
||||||
return std::to_string(r2);
|
return std::to_string(r2);
|
||||||
case ARTIFACT_TYPE:
|
case EType::ARTIFACT_TYPE:
|
||||||
return ((deal->isBlocked()) ? "0" : "1");
|
return ((deal->isBlocked()) ? "0" : "1");
|
||||||
case PLAYER:
|
case EType::PLAYER:
|
||||||
return (hRight ? CGI->generaltexth->capColors[hRight->id] : "");
|
return (hRight ? CGI->generaltexth->capColors[hRight->id] : "");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -587,11 +595,11 @@ Point CMarketplaceWindow::selectionOffset(bool Left) const
|
|||||||
{
|
{
|
||||||
switch(itemsType[1])
|
switch(itemsType[1])
|
||||||
{
|
{
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
return Point(122, 448);
|
return Point(122, 448);
|
||||||
case CREATURE:
|
case EType::CREATURE:
|
||||||
return Point(128, 450);
|
return Point(128, 450);
|
||||||
case ARTIFACT_INSTANCE:
|
case EType::ARTIFACT_INSTANCE:
|
||||||
return Point(134, 469);
|
return Point(134, 469);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -599,14 +607,14 @@ Point CMarketplaceWindow::selectionOffset(bool Left) const
|
|||||||
{
|
{
|
||||||
switch(itemsType[0])
|
switch(itemsType[0])
|
||||||
{
|
{
|
||||||
case RESOURCE:
|
case EType::RESOURCE:
|
||||||
if(mode == EMarketMode::ARTIFACT_RESOURCE)
|
if(mode == EMarketMode::ARTIFACT_RESOURCE)
|
||||||
return Point(410, 471);
|
return Point(410, 471);
|
||||||
else
|
else
|
||||||
return Point(410, 448);
|
return Point(410, 448);
|
||||||
case ARTIFACT_TYPE:
|
case EType::ARTIFACT_TYPE:
|
||||||
return Point(411, 449);
|
return Point(411, 449);
|
||||||
case PLAYER:
|
case EType::PLAYER:
|
||||||
return Point(417, 451);
|
return Point(417, 451);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -9,7 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../widgets/CTradeBase.h"
|
#include "../widgets/markets/CTradeBase.h"
|
||||||
#include "../widgets/CWindowWithArtifacts.h"
|
#include "../widgets/CWindowWithArtifacts.h"
|
||||||
#include "CWindowObject.h"
|
#include "CWindowObject.h"
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user