mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-12 02:28:11 +02:00
Creatures altar & Artifacts altar
This commit is contained in:
parent
9f9317a8a0
commit
75ebd954af
@ -93,6 +93,7 @@ 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
|
||||||
@ -115,6 +116,7 @@ set(client_SRCS
|
|||||||
widgets/CWindowWithArtifacts.cpp
|
widgets/CWindowWithArtifacts.cpp
|
||||||
widgets/RadialMenu.cpp
|
widgets/RadialMenu.cpp
|
||||||
|
|
||||||
|
windows/CAltarWindow.cpp
|
||||||
windows/CCastleInterface.cpp
|
windows/CCastleInterface.cpp
|
||||||
windows/CCreatureWindow.cpp
|
windows/CCreatureWindow.cpp
|
||||||
windows/CHeroOverview.cpp
|
windows/CHeroOverview.cpp
|
||||||
@ -260,6 +262,7 @@ 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
|
||||||
@ -282,6 +285,7 @@ set(client_HEADERS
|
|||||||
widgets/CWindowWithArtifacts.h
|
widgets/CWindowWithArtifacts.h
|
||||||
widgets/RadialMenu.h
|
widgets/RadialMenu.h
|
||||||
|
|
||||||
|
windows/CAltarWindow.h
|
||||||
windows/CCastleInterface.h
|
windows/CCastleInterface.h
|
||||||
windows/CCreatureWindow.h
|
windows/CCreatureWindow.h
|
||||||
windows/CHeroOverview.h
|
windows/CHeroOverview.h
|
||||||
|
@ -48,6 +48,7 @@
|
|||||||
#include "widgets/CComponent.h"
|
#include "widgets/CComponent.h"
|
||||||
#include "widgets/CGarrisonInt.h"
|
#include "widgets/CGarrisonInt.h"
|
||||||
|
|
||||||
|
#include "windows/CAltarWindow.h"
|
||||||
#include "windows/CCastleInterface.h"
|
#include "windows/CCastleInterface.h"
|
||||||
#include "windows/CCreatureWindow.h"
|
#include "windows/CCreatureWindow.h"
|
||||||
#include "windows/CHeroWindow.h"
|
#include "windows/CHeroWindow.h"
|
||||||
@ -421,7 +422,7 @@ void CPlayerInterface::heroPrimarySkillChanged(const CGHeroInstance * hero, Prim
|
|||||||
if (which == PrimarySkill::EXPERIENCE)
|
if (which == PrimarySkill::EXPERIENCE)
|
||||||
{
|
{
|
||||||
for (auto ctw : GH.windows().findWindows<CAltarWindow>())
|
for (auto ctw : GH.windows().findWindows<CAltarWindow>())
|
||||||
ctw->setExpToLevel();
|
ctw->updateExpToLevel();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
adventureInt->onHeroChanged(hero);
|
adventureInt->onHeroChanged(hero);
|
||||||
@ -558,10 +559,10 @@ void CPlayerInterface::garrisonsChanged(std::vector<const CGObjectInstance *> ob
|
|||||||
for (auto cgh : GH.windows().findWindows<IGarrisonHolder>())
|
for (auto cgh : GH.windows().findWindows<IGarrisonHolder>())
|
||||||
cgh->updateGarrisons();
|
cgh->updateGarrisons();
|
||||||
|
|
||||||
for (auto cmw : GH.windows().findWindows<CTradeWindow>())
|
for (auto cmw : GH.windows().findWindows<CAltarWindow>())
|
||||||
{
|
{
|
||||||
if (vstd::contains(objs, cmw->hero))
|
if(vstd::contains(objs, cmw->getHero()))
|
||||||
cmw->garrisonChanged();
|
cmw->updateGarrison();
|
||||||
}
|
}
|
||||||
|
|
||||||
GH.windows().totalRedraw();
|
GH.windows().totalRedraw();
|
||||||
|
457
client/widgets/CAltar.cpp
Normal file
457
client/widgets/CAltar.cpp
Normal file
@ -0,0 +1,457 @@
|
|||||||
|
/*
|
||||||
|
* 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 "../widgets/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"
|
||||||
|
|
||||||
|
CAltar::CAltar(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
: CTradeBase(market, hero)
|
||||||
|
{
|
||||||
|
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 = std::make_shared<CButton>(Point(269, 520), AnimationPath::builtin("ALTSACR.DEF"), CGI->generaltexth->zelp[585], std::bind(&CAltar::makeDeal, this));
|
||||||
|
expToLevel = std::make_shared<CLabel>(75, 477, FONT_SMALL, ETextAlignment::CENTER);
|
||||||
|
expForHero = std::make_shared<CLabel>(75, 545, FONT_SMALL, ETextAlignment::CENTER);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltar::deselect()
|
||||||
|
{
|
||||||
|
hLeft = hRight = nullptr;
|
||||||
|
deal->block(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
: CAltar(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(&CAltar::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, -10));
|
||||||
|
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 = [this](std::shared_ptr<CTradeableItem> altarSlot) -> void
|
||||||
|
{
|
||||||
|
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();
|
||||||
|
};
|
||||||
|
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<ui32> positions;
|
||||||
|
for(const auto art : arts->artifactsOnAltar)
|
||||||
|
{
|
||||||
|
positions.push_back(hero->getSlotByInstance(art));
|
||||||
|
}
|
||||||
|
std::sort(positions.begin(), positions.end(), std::greater<>());
|
||||||
|
|
||||||
|
LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, {}, {}, 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;
|
||||||
|
};
|
||||||
|
|
||||||
|
CAltarCreatures::CAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
: CAltar(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);
|
||||||
|
|
||||||
|
unitsSlider = std::make_shared<CSlider>(Point(231, 481), 137, [this](int newVal) -> void
|
||||||
|
{
|
||||||
|
if(hLeft)
|
||||||
|
unitsOnAltar[hLeft->serial] = newVal;
|
||||||
|
if(hRight)
|
||||||
|
updateAltarSlot(hRight);
|
||||||
|
deal->block(calcExpAltarForHero() == 0);
|
||||||
|
updateControls();
|
||||||
|
updateSubtitlesForSelected();
|
||||||
|
}, 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, unitsSlider));
|
||||||
|
|
||||||
|
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(&CAltar::sacrificeAll, this));
|
||||||
|
|
||||||
|
auto clickPressed = [this](std::shared_ptr<CTradeableItem> altarSlot, std::vector<std::shared_ptr<CTradeableItem>> & oppositeSlots,
|
||||||
|
std::shared_ptr<CTradeableItem> & hCurSide, std::shared_ptr<CTradeableItem> & hOppSide) -> void
|
||||||
|
{
|
||||||
|
std::shared_ptr<CTradeableItem> oppositeSlot;
|
||||||
|
for(const auto & slot : oppositeSlots)
|
||||||
|
if(slot->serial == altarSlot->serial)
|
||||||
|
{
|
||||||
|
oppositeSlot = slot;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(hCurSide != altarSlot && oppositeSlot)
|
||||||
|
{
|
||||||
|
hCurSide = altarSlot;
|
||||||
|
hOppSide = oppositeSlot;
|
||||||
|
updateControls();
|
||||||
|
updateSubtitlesForSelected();
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
for(int slotIdx = 0; slotIdx < GameConstants::ARMY_SIZE; slotIdx++)
|
||||||
|
{
|
||||||
|
CreatureID creatureId = CreatureID::NONE;
|
||||||
|
if(const auto & creature = hero->getCreature(SlotID(slotIdx)))
|
||||||
|
creatureId = creature->getId();
|
||||||
|
else
|
||||||
|
continue;
|
||||||
|
|
||||||
|
auto heroSlot = std::make_shared<CTradeableItem>(posSlotsHero[slotIdx], EType::CREATURE, creatureId.num, true, slotIdx);
|
||||||
|
heroSlot->clickPressedCallback = [this, clickPressed](std::shared_ptr<CTradeableItem> altarSlot) -> void
|
||||||
|
{
|
||||||
|
clickPressed(altarSlot, items[0], hLeft, hRight);
|
||||||
|
};
|
||||||
|
heroSlot->subtitle = std::to_string(hero->getStackCount(SlotID(slotIdx)));
|
||||||
|
items[1].emplace_back(heroSlot);
|
||||||
|
}
|
||||||
|
assert(items[1].size() <= posSlotsAltar.size());
|
||||||
|
for(const auto & heroSlot : items[1])
|
||||||
|
{
|
||||||
|
auto altarSlot = std::make_shared<CTradeableItem>(posSlotsAltar[heroSlot->serial], EType::CREATURE_PLACEHOLDER, heroSlot->id, false, heroSlot->serial);
|
||||||
|
altarSlot->pos.w = heroSlot->pos.w; altarSlot->pos.h = heroSlot->pos.h;
|
||||||
|
altarSlot->clickPressedCallback = [this, clickPressed](std::shared_ptr<CTradeableItem> altarSlot) -> void
|
||||||
|
{
|
||||||
|
clickPressed(altarSlot, items[1], hRight, hLeft);
|
||||||
|
};
|
||||||
|
items[0].emplace_back(altarSlot);
|
||||||
|
}
|
||||||
|
|
||||||
|
readExpValues();
|
||||||
|
calcExpAltarForHero();
|
||||||
|
deselect();
|
||||||
|
};
|
||||||
|
|
||||||
|
void CAltarCreatures::readExpValues()
|
||||||
|
{
|
||||||
|
int dump;
|
||||||
|
for(auto heroSlot : items[1])
|
||||||
|
{
|
||||||
|
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--;
|
||||||
|
}
|
||||||
|
unitsSlider->setAmount(sliderAmount);
|
||||||
|
unitsSlider->block(!unitsSlider->getAmount());
|
||||||
|
if(hLeft)
|
||||||
|
unitsSlider->scrollTo(unitsOnAltar[hLeft->serial]);
|
||||||
|
maxUnits->block(unitsSlider->getAmount() == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::updateSubtitlesForSelected()
|
||||||
|
{
|
||||||
|
if(hLeft)
|
||||||
|
lSubtitle->setText(std::to_string(unitsSlider->getValue()));
|
||||||
|
else
|
||||||
|
lSubtitle->setText("");
|
||||||
|
if(hRight)
|
||||||
|
rSubtitle->setText(hRight->subtitle);
|
||||||
|
else
|
||||||
|
rSubtitle->setText("");
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::updateGarrison()
|
||||||
|
{
|
||||||
|
std::set<std::shared_ptr<CTradeableItem>> empty;
|
||||||
|
getEmptySlots(empty);
|
||||||
|
removeItems(empty);
|
||||||
|
readExpValues();
|
||||||
|
for(auto & heroSlot : items[1])
|
||||||
|
heroSlot->subtitle = std::to_string(hero->getStackCount(SlotID(heroSlot->serial)));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::deselect()
|
||||||
|
{
|
||||||
|
CAltar::deselect();
|
||||||
|
unitsSlider->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();
|
||||||
|
unitsSlider->scrollTo(0);
|
||||||
|
expForHero->setText(std::to_string(0));
|
||||||
|
|
||||||
|
std::vector<ui32> ids;
|
||||||
|
std::vector<ui32> toSacrifice;
|
||||||
|
|
||||||
|
for(int i = 0; i < unitsOnAltar.size(); i++)
|
||||||
|
{
|
||||||
|
if(unitsOnAltar[i])
|
||||||
|
{
|
||||||
|
ids.push_back(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 : items[0])
|
||||||
|
{
|
||||||
|
heroSlot->setType(CREATURE_PLACEHOLDER);
|
||||||
|
heroSlot->subtitle = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarCreatures::sacrificeAll()
|
||||||
|
{
|
||||||
|
std::optional<SlotID> lastSlot;
|
||||||
|
for(auto heroSlot : items[1])
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
unitsSlider->scrollTo(unitsOnAltar[hRight->serial]);
|
||||||
|
for(auto altarSlot : items[0])
|
||||||
|
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]))) : "";
|
||||||
|
}
|
98
client/widgets/CAltar.h
Normal file
98
client/widgets/CAltar.h
Normal file
@ -0,0 +1,98 @@
|
|||||||
|
/*
|
||||||
|
* CAltar.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../widgets/CArtifactsOfHeroAltar.h"
|
||||||
|
#include "../widgets/CTradeBase.h"
|
||||||
|
|
||||||
|
class CSlider;
|
||||||
|
|
||||||
|
class CAltar : public CTradeBase, public CIntObject
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
std::shared_ptr<CLabel> expToLevel;
|
||||||
|
std::shared_ptr<CLabel> expForHero;
|
||||||
|
std::shared_ptr<CButton> sacrificeAllButton;
|
||||||
|
|
||||||
|
CAltar(const IMarket * market, const CGHeroInstance * hero);
|
||||||
|
virtual ~CAltar() = default;
|
||||||
|
virtual void sacrificeAll() = 0;
|
||||||
|
virtual void deselect();
|
||||||
|
virtual TExpType calcExpAltarForHero() = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class CAltarArtifacts : public CAltar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CAltarArtifacts(const IMarket * market, const CGHeroInstance * hero);
|
||||||
|
TExpType calcExpAltarForHero() override;
|
||||||
|
void makeDeal() override;
|
||||||
|
void sacrificeAll() override;
|
||||||
|
void sacrificeBackpack();
|
||||||
|
void setSelectedArtifact(const CArtifactInstance * art);
|
||||||
|
void moveArtToAltar(std::shared_ptr<CTradeableItem>, const CArtifactInstance * art);
|
||||||
|
std::shared_ptr<CArtifactsOfHeroAltar> getAOHset() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::shared_ptr<CArtPlace> selectedArt;
|
||||||
|
std::shared_ptr<CLabel> selectedCost;
|
||||||
|
std::shared_ptr<CButton> sacrificeBackpackButton;
|
||||||
|
std::shared_ptr<CArtifactsOfHeroAltar> arts;
|
||||||
|
|
||||||
|
const std::vector<Point> posSlotsAltar =
|
||||||
|
{
|
||||||
|
Point(317, 53), Point(371, 53), Point(425, 53),
|
||||||
|
Point(479, 53), Point(533, 53), Point(317, 123),
|
||||||
|
Point(371, 123), Point(425, 123), Point(479, 123),
|
||||||
|
Point(533, 123), Point(317, 193), Point(371, 193),
|
||||||
|
Point(425, 193), Point(479, 193), Point(533, 193),
|
||||||
|
Point(317, 263), Point(371, 263), Point(425, 263),
|
||||||
|
Point(479, 263), Point(533, 263), Point(398, 333),
|
||||||
|
Point(452, 333)
|
||||||
|
};
|
||||||
|
|
||||||
|
bool putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art);
|
||||||
|
};
|
||||||
|
|
||||||
|
class CAltarCreatures : public CAltar
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CAltarCreatures(const IMarket * market, const CGHeroInstance * hero);
|
||||||
|
void updateGarrison();
|
||||||
|
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::shared_ptr<CSlider> unitsSlider;
|
||||||
|
std::vector<int> unitsOnAltar;
|
||||||
|
std::vector<int> expPerUnit;
|
||||||
|
std::shared_ptr<CLabel> lSubtitle, rSubtitle;
|
||||||
|
|
||||||
|
const std::vector<Point> posSlotsAltar =
|
||||||
|
{
|
||||||
|
Point(334, 110), Point(417, 110), Point(500, 110),
|
||||||
|
Point(334, 208), Point(417, 208), Point(500, 208),
|
||||||
|
Point(417, 306)
|
||||||
|
};
|
||||||
|
const std::vector<Point> posSlotsHero =
|
||||||
|
{
|
||||||
|
Point(45, 110), Point(128, 110), Point(211, 110),
|
||||||
|
Point(45, 208), Point(128, 208), Point(211, 208),
|
||||||
|
Point(128, 306)
|
||||||
|
};
|
||||||
|
|
||||||
|
void readExpValues();
|
||||||
|
void updateControls();
|
||||||
|
void updateSubtitlesForSelected();
|
||||||
|
};
|
@ -31,6 +31,11 @@ CTradeBase::CTradeableItem::CTradeableItem(Point pos, EType Type, int ID, bool L
|
|||||||
downSelection = false;
|
downSelection = false;
|
||||||
hlp = nullptr;
|
hlp = nullptr;
|
||||||
setType(Type);
|
setType(Type);
|
||||||
|
if(image)
|
||||||
|
{
|
||||||
|
this->pos.w = image->pos.w;
|
||||||
|
this->pos.h = image->pos.h;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CTradeBase::CTradeableItem::setType(EType newType)
|
void CTradeBase::CTradeableItem::setType(EType newType)
|
||||||
@ -124,14 +129,14 @@ void CTradeBase::CTradeableItem::showAll(Canvas & to)
|
|||||||
break;
|
break;
|
||||||
case CREATURE_PLACEHOLDER:
|
case CREATURE_PLACEHOLDER:
|
||||||
case CREATURE:
|
case CREATURE:
|
||||||
posToSubCenter = Point(29, 76);
|
posToSubCenter = Point(29, 77);
|
||||||
break;
|
break;
|
||||||
case PLAYER:
|
case PLAYER:
|
||||||
posToSubCenter = Point(31, 76);
|
posToSubCenter = Point(31, 76);
|
||||||
break;
|
break;
|
||||||
case ARTIFACT_PLACEHOLDER:
|
case ARTIFACT_PLACEHOLDER:
|
||||||
case ARTIFACT_INSTANCE:
|
case ARTIFACT_INSTANCE:
|
||||||
posToSubCenter = Point(19, 55);
|
posToSubCenter = Point(19, 54);
|
||||||
if (downSelection)
|
if (downSelection)
|
||||||
posToSubCenter.y += 8;
|
posToSubCenter.y += 8;
|
||||||
break;
|
break;
|
||||||
|
136
client/windows/CAltarWindow.cpp
Normal file
136
client/windows/CAltarWindow.cpp
Normal file
@ -0,0 +1,136 @@
|
|||||||
|
/*
|
||||||
|
* 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 "CAltarWindow.h"
|
||||||
|
|
||||||
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../render/Canvas.h"
|
||||||
|
#include "../gui/Shortcut.h"
|
||||||
|
#include "../widgets/Buttons.h"
|
||||||
|
#include "../widgets/TextControls.h"
|
||||||
|
|
||||||
|
#include "../CGameInfo.h"
|
||||||
|
|
||||||
|
#include "../../lib/CGeneralTextHandler.h"
|
||||||
|
#include "../../lib/CHeroHandler.h"
|
||||||
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
|
||||||
|
CAltarWindow::CAltarWindow(const IMarket * market, const CGHeroInstance * hero, const std::function<void()> & onWindowClosed, EMarketMode mode)
|
||||||
|
: CWindowObject(PLAYER_COLORED, ImagePath::builtin(mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"))
|
||||||
|
, hero(hero)
|
||||||
|
, windowClosedCallback(onWindowClosed)
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
|
if(mode == EMarketMode::ARTIFACT_EXP)
|
||||||
|
createAltarArtifacts(market, hero);
|
||||||
|
else if (mode == EMarketMode::CREATURE_EXP)
|
||||||
|
createAltarCreatures(market, hero);
|
||||||
|
else
|
||||||
|
close();
|
||||||
|
updateExpToLevel();
|
||||||
|
statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarWindow::updateExpToLevel()
|
||||||
|
{
|
||||||
|
altar->expToLevel->setText(std::to_string(CGI->heroh->reqExp(CGI->heroh->level(altar->hero->exp) + 1) - altar->hero->exp));
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarWindow::updateGarrison()
|
||||||
|
{
|
||||||
|
if(auto altarCreatures = std::static_pointer_cast<CAltarCreatures>(altar))
|
||||||
|
altarCreatures->updateGarrison();
|
||||||
|
}
|
||||||
|
|
||||||
|
const CGHeroInstance * CAltarWindow::getHero() const
|
||||||
|
{
|
||||||
|
return hero;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarWindow::close()
|
||||||
|
{
|
||||||
|
if(windowClosedCallback)
|
||||||
|
windowClosedCallback();
|
||||||
|
|
||||||
|
CWindowObject::close();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarWindow::createAltarArtifacts(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
|
background = createBg(ImagePath::builtin("ALTRART2.bmp"), PLAYER_COLORED);
|
||||||
|
|
||||||
|
auto altarArtifacts = std::make_shared<CAltarArtifacts>(market, hero);
|
||||||
|
altar = altarArtifacts;
|
||||||
|
artSets.clear();
|
||||||
|
addSetAndCallbacks(altarArtifacts->getAOHset());
|
||||||
|
|
||||||
|
changeModeButton = std::make_shared<CButton>(Point(516, 421), AnimationPath::builtin("ALTSACC.DEF"),
|
||||||
|
CGI->generaltexth->zelp[572], std::bind(&CAltarWindow::createAltarCreatures, this, market, hero));
|
||||||
|
if(altar->hero->getAlignment() == EAlignment::GOOD)
|
||||||
|
changeModeButton->block(true);
|
||||||
|
quitButton = std::make_shared<CButton>(Point(516, 520), AnimationPath::builtin("IOK6432.DEF"),
|
||||||
|
CGI->generaltexth->zelp[568], std::bind(&CAltarWindow::close, this), EShortcut::GLOBAL_RETURN);
|
||||||
|
altar->setRedrawParent(true);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarWindow::createAltarCreatures(const IMarket * market, const CGHeroInstance * hero)
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255 - DISPOSE);
|
||||||
|
|
||||||
|
background = createBg(ImagePath::builtin("ALTARMON.bmp"), PLAYER_COLORED);
|
||||||
|
|
||||||
|
altar = std::make_shared<CAltarCreatures>(market, hero);
|
||||||
|
|
||||||
|
changeModeButton = std::make_shared<CButton>(Point(516, 421), AnimationPath::builtin("ALTART.DEF"),
|
||||||
|
CGI->generaltexth->zelp[580], std::bind(&CAltarWindow::createAltarArtifacts, this, market, hero));
|
||||||
|
if(altar->hero->getAlignment() == EAlignment::EVIL)
|
||||||
|
changeModeButton->block(true);
|
||||||
|
quitButton = std::make_shared<CButton>(Point(516, 520), AnimationPath::builtin("IOK6432.DEF"),
|
||||||
|
CGI->generaltexth->zelp[568], std::bind(&CAltarWindow::close, this), EShortcut::GLOBAL_RETURN);
|
||||||
|
altar->setRedrawParent(true);
|
||||||
|
redraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarWindow::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw)
|
||||||
|
{
|
||||||
|
if(!getState().has_value())
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(auto altarArtifacts = std::static_pointer_cast<CAltarArtifacts>(altar))
|
||||||
|
{
|
||||||
|
if(const auto pickedArt = getPickedArtifact())
|
||||||
|
altarArtifacts->setSelectedArtifact(pickedArt);
|
||||||
|
else
|
||||||
|
altarArtifacts->setSelectedArtifact(nullptr);
|
||||||
|
}
|
||||||
|
CWindowWithArtifacts::artifactMoved(srcLoc, destLoc, withRedraw);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAltarWindow::showAll(Canvas & to)
|
||||||
|
{
|
||||||
|
// This func is temporary workaround for compliance with CTradeWindow
|
||||||
|
CWindowObject::showAll(to);
|
||||||
|
|
||||||
|
if(altar->hRight)
|
||||||
|
{
|
||||||
|
to.drawBorder(Rect::createAround(altar->hRight->pos, 1), Colors::BRIGHT_YELLOW, 2);
|
||||||
|
altar->hRight->showAllAt(altar->pos.topLeft() + Point(396, 423), "", to);
|
||||||
|
}
|
||||||
|
if(altar->hLeft)
|
||||||
|
{
|
||||||
|
to.drawBorder(Rect::createAround(altar->hLeft->pos, 1), Colors::BRIGHT_YELLOW, 2);
|
||||||
|
altar->hLeft->showAllAt(altar->pos.topLeft() + Point(150, 423), "", to);
|
||||||
|
}
|
||||||
|
}
|
38
client/windows/CAltarWindow.h
Normal file
38
client/windows/CAltarWindow.h
Normal file
@ -0,0 +1,38 @@
|
|||||||
|
/*
|
||||||
|
* CAltarWindow.h, part of VCMI engine
|
||||||
|
*
|
||||||
|
* Authors: listed in file AUTHORS in main folder
|
||||||
|
*
|
||||||
|
* License: GNU General Public License v2.0 or later
|
||||||
|
* Full text of license available in license.txt file, in main folder
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include "../widgets/CAltar.h"
|
||||||
|
#include "../widgets/CWindowWithArtifacts.h"
|
||||||
|
#include "CWindowObject.h"
|
||||||
|
|
||||||
|
class CAltarWindow : public CWindowObject, public CWindowWithArtifacts
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
CAltarWindow(const IMarket * market, const CGHeroInstance * hero, const std::function<void()> & onWindowClosed, EMarketMode mode);
|
||||||
|
void updateExpToLevel();
|
||||||
|
void updateGarrison();
|
||||||
|
const CGHeroInstance * getHero() const;
|
||||||
|
void close() override;
|
||||||
|
|
||||||
|
void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) override;
|
||||||
|
void showAll(Canvas & to) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
const CGHeroInstance * hero;
|
||||||
|
std::shared_ptr<CAltar> altar;
|
||||||
|
std::shared_ptr<CButton> changeModeButton;
|
||||||
|
std::shared_ptr<CButton> quitButton;
|
||||||
|
std::function<void()> windowClosedCallback;
|
||||||
|
std::shared_ptr<CGStatusBar> statusBar;
|
||||||
|
|
||||||
|
void createAltarArtifacts(const IMarket * market, const CGHeroInstance * hero);
|
||||||
|
void createAltarCreatures(const IMarket * market, const CGHeroInstance * hero);
|
||||||
|
};
|
@ -66,14 +66,6 @@ void CTradeWindow::initTypes()
|
|||||||
itemsType[1] = ARTIFACT_INSTANCE;
|
itemsType[1] = ARTIFACT_INSTANCE;
|
||||||
itemsType[0] = RESOURCE;
|
itemsType[0] = RESOURCE;
|
||||||
break;
|
break;
|
||||||
case EMarketMode::CREATURE_EXP:
|
|
||||||
itemsType[1] = CREATURE;
|
|
||||||
itemsType[0] = CREATURE_PLACEHOLDER;
|
|
||||||
break;
|
|
||||||
case EMarketMode::ARTIFACT_EXP:
|
|
||||||
itemsType[1] = ARTIFACT_TYPE;
|
|
||||||
itemsType[0] = ARTIFACT_PLACEHOLDER;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -145,26 +137,7 @@ std::vector<int> *CTradeWindow::getItemsIds(bool Left)
|
|||||||
{
|
{
|
||||||
std::vector<int> *ids = nullptr;
|
std::vector<int> *ids = nullptr;
|
||||||
|
|
||||||
if(mode == EMarketMode::ARTIFACT_EXP)
|
if(!Left)
|
||||||
return new std::vector<int>(22, -1);
|
|
||||||
|
|
||||||
if(Left)
|
|
||||||
{
|
|
||||||
switch(itemsType[1])
|
|
||||||
{
|
|
||||||
case CREATURE:
|
|
||||||
ids = new std::vector<int>;
|
|
||||||
for(int i = 0; i < 7; i++)
|
|
||||||
{
|
|
||||||
if(const CCreature *c = hero->getCreature(SlotID(i)))
|
|
||||||
ids->push_back(c->getId());
|
|
||||||
else
|
|
||||||
ids->push_back(-1);
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
switch(itemsType[0])
|
switch(itemsType[0])
|
||||||
{
|
{
|
||||||
@ -186,50 +159,31 @@ std::vector<int> *CTradeWindow::getItemsIds(bool Left)
|
|||||||
|
|
||||||
void CTradeWindow::getPositionsFor(std::vector<Rect> &poss, bool Left, EType type) const
|
void CTradeWindow::getPositionsFor(std::vector<Rect> &poss, bool Left, EType type) const
|
||||||
{
|
{
|
||||||
if(mode == EMarketMode::ARTIFACT_EXP && !Left)
|
//seven boxes:
|
||||||
|
// X X X
|
||||||
|
// X X X
|
||||||
|
// X
|
||||||
|
int h, w, x, y, dx, dy;
|
||||||
|
int leftToRightOffset;
|
||||||
|
getBaseForPositions(type, dx, dy, x, y, h, w, !Left, leftToRightOffset);
|
||||||
|
|
||||||
|
const std::vector<Rect> tmp =
|
||||||
{
|
{
|
||||||
//22 boxes, 5 in row, last row: two boxes centered
|
Rect(Point(x + 0 * dx, y + 0 * dx), Point(w, h) ),
|
||||||
int h, w, x, y, dx, dy;
|
Rect(Point(x + 1 * dx, y + 0 * dx), Point(w, h) ),
|
||||||
h = w = 44;
|
Rect(Point(x + 2 * dx, y + 0 * dx), Point(w, h) ),
|
||||||
x = 317;
|
Rect(Point(x + 0 * dx, y + 1 * dy), Point(w, h) ),
|
||||||
y = 53;
|
Rect(Point(x + 1 * dx, y + 1 * dy), Point(w, h) ),
|
||||||
dx = 54;
|
Rect(Point(x + 2 * dx, y + 1 * dy), Point(w, h) ),
|
||||||
dy = 70;
|
Rect(Point(x + 1 * dx, y + 2 * dy), Point(w, h) )
|
||||||
for (int i = 0; i < 4 ; i++)
|
};
|
||||||
for (int j = 0; j < 5 ; j++)
|
|
||||||
poss.push_back(Rect(x + dx*j, y + dy*i, w, h));
|
|
||||||
|
|
||||||
poss.push_back(Rect((int)(x + dx * 1.5), (y + dy * 4), w, h));
|
vstd::concatenate(poss, tmp);
|
||||||
poss.push_back(Rect((int)(x + dx * 2.5), (y + dy * 4), w, h));
|
|
||||||
}
|
if(!Left)
|
||||||
else
|
|
||||||
{
|
{
|
||||||
//seven boxes:
|
for(Rect &r : poss)
|
||||||
// X X X
|
r.x += leftToRightOffset;
|
||||||
// X X X
|
|
||||||
// X
|
|
||||||
int h, w, x, y, dx, dy;
|
|
||||||
int leftToRightOffset;
|
|
||||||
getBaseForPositions(type, dx, dy, x, y, h, w, !Left, leftToRightOffset);
|
|
||||||
|
|
||||||
const std::vector<Rect> tmp =
|
|
||||||
{
|
|
||||||
Rect(Point(x + 0 * dx, y + 0 * dx), Point(w, h) ),
|
|
||||||
Rect(Point(x + 1 * dx, y + 0 * dx), Point(w, h) ),
|
|
||||||
Rect(Point(x + 2 * dx, y + 0 * dx), Point(w, h) ),
|
|
||||||
Rect(Point(x + 0 * dx, y + 1 * dy), Point(w, h) ),
|
|
||||||
Rect(Point(x + 1 * dx, y + 1 * dy), Point(w, h) ),
|
|
||||||
Rect(Point(x + 2 * dx, y + 1 * dy), Point(w, h) ),
|
|
||||||
Rect(Point(x + 1 * dx, y + 2 * dy), Point(w, h) )
|
|
||||||
};
|
|
||||||
|
|
||||||
vstd::concatenate(poss, tmp);
|
|
||||||
|
|
||||||
if(!Left)
|
|
||||||
{
|
|
||||||
for(Rect &r : poss)
|
|
||||||
r.x += leftToRightOffset;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -288,9 +242,9 @@ void CTradeWindow::showAll(Canvas & to)
|
|||||||
if(readyToTrade)
|
if(readyToTrade)
|
||||||
{
|
{
|
||||||
if(hLeft)
|
if(hLeft)
|
||||||
hLeft->showAllAt(pos.topLeft() + selectionOffset(true), selectionSubtitle(true), to);
|
hLeft->showAllAt(pos.topLeft() + selectionOffset(true), updateSlotSubtitle(true), to);
|
||||||
if(hRight)
|
if(hRight)
|
||||||
hRight->showAllAt(pos.topLeft() + selectionOffset(false), selectionSubtitle(false), to);
|
hRight->showAllAt(pos.topLeft() + selectionOffset(false), updateSlotSubtitle(false), to);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -315,7 +269,6 @@ void CTradeWindow::setMode(EMarketMode Mode)
|
|||||||
{
|
{
|
||||||
case EMarketMode::CREATURE_EXP:
|
case EMarketMode::CREATURE_EXP:
|
||||||
case EMarketMode::ARTIFACT_EXP:
|
case EMarketMode::ARTIFACT_EXP:
|
||||||
GH.windows().createAndPushWindow<CAltarWindow>(m, h, functor, Mode);
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GH.windows().createAndPushWindow<CMarketplaceWindow>(m, h, functor, Mode);
|
GH.windows().createAndPushWindow<CMarketplaceWindow>(m, h, functor, Mode);
|
||||||
@ -612,7 +565,7 @@ bool CMarketplaceWindow::printButtonFor(EMarketMode M) const
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CMarketplaceWindow::garrisonChanged()
|
void CMarketplaceWindow::updateGarrison()
|
||||||
{
|
{
|
||||||
if(mode != EMarketMode::CREATURE_RESOURCE)
|
if(mode != EMarketMode::CREATURE_RESOURCE)
|
||||||
return;
|
return;
|
||||||
@ -642,7 +595,7 @@ void CMarketplaceWindow::artifactsChanged(bool Left)
|
|||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string CMarketplaceWindow::selectionSubtitle(bool Left) const
|
std::string CMarketplaceWindow::updateSlotSubtitle(bool Left) const
|
||||||
{
|
{
|
||||||
if(Left)
|
if(Left)
|
||||||
{
|
{
|
||||||
@ -811,431 +764,3 @@ void CMarketplaceWindow::updateTraderText()
|
|||||||
}
|
}
|
||||||
traderText->setText(CGI->generaltexth->allTexts[gnrtxtnr]);
|
traderText->setText(CGI->generaltexth->allTexts[gnrtxtnr]);
|
||||||
}
|
}
|
||||||
|
|
||||||
CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode)
|
|
||||||
: CTradeWindow(ImagePath::builtin(Mode == EMarketMode::CREATURE_EXP ? "ALTARMON.bmp" : "ALTRART2.bmp"), Market, Hero, onWindowClosed, Mode)
|
|
||||||
{
|
|
||||||
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
|
||||||
|
|
||||||
if(Mode == EMarketMode::CREATURE_EXP)
|
|
||||||
{
|
|
||||||
//%s's Creatures
|
|
||||||
labels.push_back(std::make_shared<CLabel>(155, 30, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW,
|
|
||||||
boost::str(boost::format(CGI->generaltexth->allTexts[272]) % hero->getNameTranslated())));
|
|
||||||
|
|
||||||
//Altar of Sacrifice
|
|
||||||
labels.push_back(std::make_shared<CLabel>(450, 30, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[479]));
|
|
||||||
|
|
||||||
//To sacrifice creatures, move them from your army on to the Altar and click Sacrifice
|
|
||||||
new CTextBox(CGI->generaltexth->allTexts[480], Rect(320, 56, 256, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW);
|
|
||||||
|
|
||||||
slider = std::make_shared<CSlider>(Point(231, 481), 137, std::bind(&CAltarWindow::sliderMoved, this, _1), 0, 0, 0, Orientation::HORIZONTAL);
|
|
||||||
max = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("IRCBTNS.DEF"), CGI->generaltexth->zelp[578], std::bind(&CSlider::scrollToMax, slider));
|
|
||||||
|
|
||||||
sacrificedUnits.resize(GameConstants::ARMY_SIZE, 0);
|
|
||||||
sacrificeAll = std::make_shared<CButton>(Point(393, 520), AnimationPath::builtin("ALTARMY.DEF"), CGI->generaltexth->zelp[579], std::bind(&CAltarWindow::SacrificeAll,this));
|
|
||||||
|
|
||||||
initItems(true);
|
|
||||||
mimicCres();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
//Sacrifice artifacts for experience
|
|
||||||
labels.push_back(std::make_shared<CLabel>(450, 34, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[477]));
|
|
||||||
//%s's Creatures
|
|
||||||
labels.push_back(std::make_shared<CLabel>(302, 423, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW, CGI->generaltexth->allTexts[478]));
|
|
||||||
|
|
||||||
sacrificeAll = std::make_shared<CButton>(Point(393, 520), AnimationPath::builtin("ALTFILL.DEF"), CGI->generaltexth->zelp[571], std::bind(&CAltarWindow::SacrificeAll,this));
|
|
||||||
sacrificeAll->block(hero->artifactsInBackpack.empty() && hero->artifactsWorn.empty());
|
|
||||||
sacrificeBackpack = std::make_shared<CButton>(Point(147, 520), AnimationPath::builtin("ALTEMBK.DEF"), CGI->generaltexth->zelp[570], std::bind(&CAltarWindow::SacrificeBackpack,this));
|
|
||||||
sacrificeBackpack->block(hero->artifactsInBackpack.empty());
|
|
||||||
|
|
||||||
arts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -12));
|
|
||||||
arts->setHero(hero);
|
|
||||||
addSetAndCallbacks(arts);
|
|
||||||
|
|
||||||
initItems(true);
|
|
||||||
initItems(false);
|
|
||||||
artIcon = std::make_shared<CAnimImage>(AnimationPath::builtin("ARTIFACT"), 0, 0, 281, 442);
|
|
||||||
artIcon->disable();
|
|
||||||
}
|
|
||||||
|
|
||||||
//Experience needed to reach next level
|
|
||||||
texts.push_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.push_back(std::make_shared<CTextBox>(CGI->generaltexth->allTexts[476], Rect(15, 495, 125, 40), 0, FONT_SMALL, ETextAlignment::CENTER, Colors::YELLOW));
|
|
||||||
|
|
||||||
statusBar = CGStatusBar::create(std::make_shared<CPicture>(background->getSurface(), Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
|
|
||||||
|
|
||||||
ok = std::make_shared<CButton>(Point(516, 520), AnimationPath::builtin("IOK6432.DEF"), CGI->generaltexth->zelp[568], [&](){ close();}, EShortcut::GLOBAL_RETURN);
|
|
||||||
|
|
||||||
deal = std::make_shared<CButton>(Point(269, 520), AnimationPath::builtin("ALTSACR.DEF"), CGI->generaltexth->zelp[585], std::bind(&CAltarWindow::makeDeal,this));
|
|
||||||
|
|
||||||
if(Mode == EMarketMode::CREATURE_EXP)
|
|
||||||
{
|
|
||||||
auto changeMode = std::make_shared<CButton>(Point(516, 421), AnimationPath::builtin("ALTART.DEF"), CGI->generaltexth->zelp[580], std::bind(&CTradeWindow::setMode,this, EMarketMode::ARTIFACT_EXP));
|
|
||||||
if(Hero->getAlignment() == ::EAlignment::EVIL)
|
|
||||||
changeMode->block(true);
|
|
||||||
buttons.push_back(changeMode);
|
|
||||||
}
|
|
||||||
else if(Mode == EMarketMode::ARTIFACT_EXP)
|
|
||||||
{
|
|
||||||
auto changeMode = std::make_shared<CButton>(Point(516, 421), AnimationPath::builtin("ALTSACC.DEF"), CGI->generaltexth->zelp[572], std::bind(&CTradeWindow::setMode,this, EMarketMode::CREATURE_EXP));
|
|
||||||
if(Hero->getAlignment() == ::EAlignment::GOOD)
|
|
||||||
changeMode->block(true);
|
|
||||||
buttons.push_back(changeMode);
|
|
||||||
}
|
|
||||||
|
|
||||||
expPerUnit.resize(GameConstants::ARMY_SIZE, 0);
|
|
||||||
getExpValues();
|
|
||||||
|
|
||||||
expToLevel = std::make_shared<CLabel>(73, 475, FONT_SMALL, ETextAlignment::CENTER);
|
|
||||||
expOnAltar = std::make_shared<CLabel>(73, 543, FONT_SMALL, ETextAlignment::CENTER);
|
|
||||||
|
|
||||||
setExpToLevel();
|
|
||||||
calcTotalExp();
|
|
||||||
blockTrade();
|
|
||||||
}
|
|
||||||
|
|
||||||
CAltarWindow::~CAltarWindow() = default;
|
|
||||||
|
|
||||||
void CAltarWindow::getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const
|
|
||||||
{
|
|
||||||
leftToRightOffset = 289;
|
|
||||||
x = 45;
|
|
||||||
y = 110;
|
|
||||||
w = 58;
|
|
||||||
h = 64;
|
|
||||||
dx = 83;
|
|
||||||
dy = 98;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::sliderMoved(int to)
|
|
||||||
{
|
|
||||||
if(hLeft)
|
|
||||||
sacrificedUnits[hLeft->serial] = to;
|
|
||||||
if(hRight)
|
|
||||||
updateRight(hRight);
|
|
||||||
|
|
||||||
deal->block(!to);
|
|
||||||
calcTotalExp();
|
|
||||||
redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::makeDeal()
|
|
||||||
{
|
|
||||||
if(mode == EMarketMode::CREATURE_EXP)
|
|
||||||
{
|
|
||||||
blockTrade();
|
|
||||||
slider->scrollTo(0);
|
|
||||||
|
|
||||||
std::vector<ui32> ids;
|
|
||||||
std::vector<ui32> toSacrifice;
|
|
||||||
|
|
||||||
for(int i = 0; i < sacrificedUnits.size(); i++)
|
|
||||||
{
|
|
||||||
if(sacrificedUnits[i])
|
|
||||||
{
|
|
||||||
ids.push_back(i);
|
|
||||||
toSacrifice.push_back(sacrificedUnits[i]);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
LOCPLINT->cb->trade(market, mode, ids, {}, toSacrifice, hero);
|
|
||||||
|
|
||||||
for(int& val : sacrificedUnits)
|
|
||||||
val = 0;
|
|
||||||
|
|
||||||
for(auto item : items[0])
|
|
||||||
{
|
|
||||||
item->setType(CREATURE_PLACEHOLDER);
|
|
||||||
item->subtitle = "";
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<ui32> positions;
|
|
||||||
for(const CArtifactInstance * art : arts->artifactsOnAltar)
|
|
||||||
{
|
|
||||||
positions.push_back(hero->getSlotByInstance(art));
|
|
||||||
}
|
|
||||||
std::sort(positions.begin(), positions.end(), std::greater<>());
|
|
||||||
|
|
||||||
LOCPLINT->cb->trade(market, mode, positions, {}, {}, hero);
|
|
||||||
arts->artifactsOnAltar.clear();
|
|
||||||
|
|
||||||
for(auto item : items[0])
|
|
||||||
{
|
|
||||||
item->setID(-1);
|
|
||||||
item->subtitle = "";
|
|
||||||
}
|
|
||||||
|
|
||||||
//arts->scrollBackpack(0);
|
|
||||||
deal->block(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
calcTotalExp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::SacrificeAll()
|
|
||||||
{
|
|
||||||
if(mode == EMarketMode::CREATURE_EXP)
|
|
||||||
{
|
|
||||||
bool movedAnything = false;
|
|
||||||
for(auto item : items[1])
|
|
||||||
sacrificedUnits[item->serial] = hero->getStackCount(SlotID(item->serial));
|
|
||||||
|
|
||||||
sacrificedUnits[items[1].front()->serial]--;
|
|
||||||
|
|
||||||
for(auto item : items[0])
|
|
||||||
{
|
|
||||||
updateRight(item);
|
|
||||||
if(item->type == CREATURE)
|
|
||||||
movedAnything = true;
|
|
||||||
}
|
|
||||||
|
|
||||||
deal->block(!movedAnything);
|
|
||||||
calcTotalExp();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
std::vector<ConstTransitivePtr<CArtifactInstance>> artsForMove;
|
|
||||||
for(const auto& slotInfo : arts->visibleArtSet.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();
|
|
||||||
}
|
|
||||||
redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::selectionChanged(bool side)
|
|
||||||
{
|
|
||||||
if(mode != EMarketMode::CREATURE_EXP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
int stackCount = 0;
|
|
||||||
for (int i = 0; i < GameConstants::ARMY_SIZE; i++)
|
|
||||||
if(hero->getStackCount(SlotID(i)) > sacrificedUnits[i])
|
|
||||||
stackCount++;
|
|
||||||
|
|
||||||
slider->setAmount(hero->getStackCount(SlotID(hLeft->serial)) - (stackCount == 1));
|
|
||||||
slider->block(!slider->getAmount());
|
|
||||||
slider->scrollTo(sacrificedUnits[hLeft->serial]);
|
|
||||||
max->block(!slider->getAmount());
|
|
||||||
selectOppositeItem(side);
|
|
||||||
readyToTrade = true;
|
|
||||||
redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::selectOppositeItem(bool side)
|
|
||||||
{
|
|
||||||
bool oppositeSide = !side;
|
|
||||||
int pos = vstd::find_pos(items[side], side ? hLeft : hRight);
|
|
||||||
int oppositePos = vstd::find_pos(items[oppositeSide], oppositeSide ? hLeft : hRight);
|
|
||||||
|
|
||||||
if(pos >= 0 && pos != oppositePos)
|
|
||||||
{
|
|
||||||
if(oppositeSide)
|
|
||||||
hLeft = items[oppositeSide][pos];
|
|
||||||
else
|
|
||||||
hRight = items[oppositeSide][pos];
|
|
||||||
|
|
||||||
selectionChanged(oppositeSide);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::mimicCres()
|
|
||||||
{
|
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
|
||||||
std::vector<Rect> positions;
|
|
||||||
getPositionsFor(positions, false, CREATURE);
|
|
||||||
|
|
||||||
for(auto item : items[1])
|
|
||||||
{
|
|
||||||
auto hlp = std::make_shared<CTradeableItem>(positions[item->serial].topLeft(), CREATURE_PLACEHOLDER, item->id, false, item->serial);
|
|
||||||
hlp->pos = positions[item->serial] + this->pos.topLeft();
|
|
||||||
items[0].push_back(hlp);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
Point CAltarWindow::selectionOffset(bool Left) const
|
|
||||||
{
|
|
||||||
if(Left)
|
|
||||||
return Point(150, 421);
|
|
||||||
else
|
|
||||||
return Point(396, 421);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string CAltarWindow::selectionSubtitle(bool Left) const
|
|
||||||
{
|
|
||||||
if(Left && slider && hLeft)
|
|
||||||
return std::to_string(slider->getValue());
|
|
||||||
else if(!Left && hRight)
|
|
||||||
return hRight->subtitle;
|
|
||||||
else
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::artifactsChanged(bool left)
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::garrisonChanged()
|
|
||||||
{
|
|
||||||
if(mode != EMarketMode::CREATURE_EXP)
|
|
||||||
return;
|
|
||||||
|
|
||||||
std::set<std::shared_ptr<CTradeableItem>> empty;
|
|
||||||
getEmptySlots(empty);
|
|
||||||
|
|
||||||
removeItems(empty);
|
|
||||||
|
|
||||||
initSubs(true);
|
|
||||||
getExpValues();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::getExpValues()
|
|
||||||
{
|
|
||||||
int dump;
|
|
||||||
for(auto item : items[1])
|
|
||||||
{
|
|
||||||
if(item->id >= 0)
|
|
||||||
market->getOffer(item->id, 0, dump, expPerUnit[item->serial], EMarketMode::CREATURE_EXP);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::calcTotalExp()
|
|
||||||
{
|
|
||||||
int val = 0;
|
|
||||||
if(mode == EMarketMode::CREATURE_EXP)
|
|
||||||
{
|
|
||||||
for (int i = 0; i < sacrificedUnits.size(); i++)
|
|
||||||
{
|
|
||||||
val += expPerUnit[i] * sacrificedUnits[i];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
auto artifactsOfHero = std::dynamic_pointer_cast<CArtifactsOfHeroAltar>(arts);
|
|
||||||
for(const CArtifactInstance * art : artifactsOfHero->artifactsOnAltar)
|
|
||||||
{
|
|
||||||
int dmp, valOfArt;
|
|
||||||
market->getOffer(art->artType->getId(), 0, dmp, valOfArt, mode);
|
|
||||||
val += valOfArt; //WAS val += valOfArt * arts->artifactsOnAltar.count(*i);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
val = static_cast<int>(hero->calculateXp(val));
|
|
||||||
expOnAltar->setText(std::to_string(val));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::setExpToLevel()
|
|
||||||
{
|
|
||||||
expToLevel->setText(std::to_string(CGI->heroh->reqExp(CGI->heroh->level(hero->exp)+1) - hero->exp));
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::blockTrade()
|
|
||||||
{
|
|
||||||
hLeft = hRight = nullptr;
|
|
||||||
readyToTrade = false;
|
|
||||||
if(slider)
|
|
||||||
{
|
|
||||||
slider->block(true);
|
|
||||||
max->block(true);
|
|
||||||
}
|
|
||||||
deal->block(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::updateRight(std::shared_ptr<CTradeableItem> toUpdate)
|
|
||||||
{
|
|
||||||
int val = sacrificedUnits[toUpdate->serial];
|
|
||||||
toUpdate->setType(val ? CREATURE : CREATURE_PLACEHOLDER);
|
|
||||||
toUpdate->subtitle = val ? boost::str(boost::format(CGI->generaltexth->allTexts[122]) % std::to_string(hero->calculateXp(val * expPerUnit[toUpdate->serial]))) : ""; //%s exp
|
|
||||||
}
|
|
||||||
|
|
||||||
int CAltarWindow::firstFreeSlot()
|
|
||||||
{
|
|
||||||
int ret = -1;
|
|
||||||
while(items[0][++ret]->id >= 0 && ret + 1 < items[0].size());
|
|
||||||
return items[0][ret]->id == -1 ? ret : -1;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::SacrificeBackpack()
|
|
||||||
{
|
|
||||||
while(!arts->visibleArtSet.artifactsInBackpack.empty())
|
|
||||||
{
|
|
||||||
if(!putOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact))
|
|
||||||
break;
|
|
||||||
};
|
|
||||||
calcTotalExp();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::artifactPicked()
|
|
||||||
{
|
|
||||||
redraw();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::showAll(Canvas & to)
|
|
||||||
{
|
|
||||||
CTradeWindow::showAll(to);
|
|
||||||
if(mode == EMarketMode::ARTIFACT_EXP && arts)
|
|
||||||
{
|
|
||||||
if(auto pickedArt = arts->getPickedArtifact())
|
|
||||||
{
|
|
||||||
artIcon->setFrame(pickedArt->artType->getIconIndex());
|
|
||||||
artIcon->showAll(to);
|
|
||||||
|
|
||||||
int dmp, val;
|
|
||||||
market->getOffer(pickedArt->getTypeId(), 0, dmp, val, EMarketMode::ARTIFACT_EXP);
|
|
||||||
val = static_cast<int>(hero->calculateXp(val));
|
|
||||||
|
|
||||||
to.drawText(Point(304, 498), FONT_SMALL, Colors::WHITE, ETextAlignment::CENTER, std::to_string(val));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
bool CAltarWindow::putOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance *art)
|
|
||||||
{
|
|
||||||
if(!art->artType->isTradable()) //special art
|
|
||||||
{
|
|
||||||
logGlobal->warn("Cannot put special artifact on altar!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(!altarSlot || altarSlot->id != -1)
|
|
||||||
{
|
|
||||||
int slotIndex = firstFreeSlot();
|
|
||||||
if(slotIndex < 0)
|
|
||||||
{
|
|
||||||
logGlobal->warn("No free slots on altar!");
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
altarSlot = items[0][slotIndex];
|
|
||||||
}
|
|
||||||
|
|
||||||
int dmp, val;
|
|
||||||
market->getOffer(art->artType->getId(), 0, dmp, val, EMarketMode::ARTIFACT_EXP);
|
|
||||||
val = static_cast<int>(hero->calculateXp(val));
|
|
||||||
|
|
||||||
arts->artifactsOnAltar.insert(art);
|
|
||||||
arts->deleteFromVisible(art);
|
|
||||||
altarSlot->setArtInstance(art);
|
|
||||||
altarSlot->subtitle = std::to_string(val);
|
|
||||||
|
|
||||||
deal->block(false);
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
void CAltarWindow::moveArtToAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance *art)
|
|
||||||
{
|
|
||||||
if(putOnAltar(altarSlot, art))
|
|
||||||
{
|
|
||||||
CCS->curh->dragAndDropCursor(nullptr);
|
|
||||||
arts->unmarkSlots();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
@ -45,16 +45,13 @@ public:
|
|||||||
virtual void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const = 0;
|
virtual void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const = 0;
|
||||||
virtual void selectionChanged(bool side) = 0; //true == left
|
virtual void selectionChanged(bool side) = 0; //true == left
|
||||||
virtual Point selectionOffset(bool Left) const = 0;
|
virtual Point selectionOffset(bool Left) const = 0;
|
||||||
virtual std::string selectionSubtitle(bool Left) const = 0;
|
virtual std::string updateSlotSubtitle(bool Left) const = 0;
|
||||||
virtual void garrisonChanged() = 0;
|
virtual void updateGarrison() = 0;
|
||||||
virtual void artifactsChanged(bool left) = 0;
|
virtual void artifactsChanged(bool left) = 0;
|
||||||
protected:
|
protected:
|
||||||
std::function<void()> onWindowClosed;
|
std::function<void()> onWindowClosed;
|
||||||
std::shared_ptr<CGStatusBar> statusBar;
|
std::shared_ptr<CGStatusBar> statusBar;
|
||||||
std::vector<std::shared_ptr<CLabel>> labels;
|
|
||||||
std::vector<std::shared_ptr<CPicture>> images;
|
std::vector<std::shared_ptr<CPicture>> images;
|
||||||
std::vector<std::shared_ptr<CButton>> buttons;
|
|
||||||
std::vector<std::shared_ptr<CTextBox>> texts;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
class CMarketplaceWindow : public CTradeWindow
|
class CMarketplaceWindow : public CTradeWindow
|
||||||
@ -78,58 +75,12 @@ public:
|
|||||||
~CMarketplaceWindow();
|
~CMarketplaceWindow();
|
||||||
|
|
||||||
Point selectionOffset(bool Left) const override;
|
Point selectionOffset(bool Left) const override;
|
||||||
std::string selectionSubtitle(bool Left) const override;
|
std::string updateSlotSubtitle(bool Left) const override;
|
||||||
|
|
||||||
void garrisonChanged() override; //removes creatures with count 0 from the list (apparently whole stack has been sold)
|
void updateGarrison() override; //removes creatures with count 0 from the list (apparently whole stack has been sold)
|
||||||
void artifactsChanged(bool left) override;
|
void artifactsChanged(bool left) override;
|
||||||
void resourceChanged();
|
void resourceChanged();
|
||||||
|
|
||||||
void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const override;
|
void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const override;
|
||||||
void updateTraderText();
|
void updateTraderText();
|
||||||
};
|
};
|
||||||
|
|
||||||
class CAltarWindow : public CTradeWindow
|
|
||||||
{
|
|
||||||
std::shared_ptr<CAnimImage> artIcon;
|
|
||||||
public:
|
|
||||||
std::vector<int> sacrificedUnits; //[slot_nr] -> how many creatures from that slot will be sacrificed
|
|
||||||
std::vector<int> expPerUnit;
|
|
||||||
|
|
||||||
std::shared_ptr<CButton> sacrificeAll;
|
|
||||||
std::shared_ptr<CButton> sacrificeBackpack;
|
|
||||||
std::shared_ptr<CLabel> expToLevel;
|
|
||||||
std::shared_ptr<CLabel> expOnAltar;
|
|
||||||
std::shared_ptr<CArtifactsOfHeroAltar> arts;
|
|
||||||
|
|
||||||
CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero, const std::function<void()> & onWindowClosed, EMarketMode Mode);
|
|
||||||
~CAltarWindow();
|
|
||||||
|
|
||||||
void getExpValues();
|
|
||||||
|
|
||||||
void selectionChanged(bool side) override; //true == left
|
|
||||||
void selectOppositeItem(bool side);
|
|
||||||
void SacrificeAll();
|
|
||||||
void SacrificeBackpack();
|
|
||||||
|
|
||||||
void putOnAltar(int backpackIndex);
|
|
||||||
bool putOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art);
|
|
||||||
void makeDeal() override;
|
|
||||||
void showAll(Canvas & to) override;
|
|
||||||
|
|
||||||
void blockTrade();
|
|
||||||
void sliderMoved(int to);
|
|
||||||
void getBaseForPositions(EType type, int &dx, int &dy, int &x, int &y, int &h, int &w, bool Right, int &leftToRightOffset) const override;
|
|
||||||
void mimicCres();
|
|
||||||
|
|
||||||
Point selectionOffset(bool Left) const override;
|
|
||||||
std::string selectionSubtitle(bool Left) const override;
|
|
||||||
void garrisonChanged() override;
|
|
||||||
void artifactsChanged(bool left) override;
|
|
||||||
void calcTotalExp();
|
|
||||||
void setExpToLevel();
|
|
||||||
void updateRight(std::shared_ptr<CTradeableItem> toUpdate);
|
|
||||||
|
|
||||||
void artifactPicked();
|
|
||||||
int firstFreeSlot();
|
|
||||||
void moveArtToAltar(std::shared_ptr<CTradeableItem>, const CArtifactInstance * art);
|
|
||||||
};
|
|
||||||
|
@ -16,8 +16,6 @@ class CGStatusBar;
|
|||||||
|
|
||||||
class CWindowObject : public WindowBase
|
class CWindowObject : public WindowBase
|
||||||
{
|
{
|
||||||
std::shared_ptr<CPicture> createBg(const ImagePath & imageName, bool playerColored);
|
|
||||||
|
|
||||||
std::vector<std::shared_ptr<CPicture>> shadowParts;
|
std::vector<std::shared_ptr<CPicture>> shadowParts;
|
||||||
|
|
||||||
void setShadow(bool on);
|
void setShadow(bool on);
|
||||||
@ -32,6 +30,7 @@ protected:
|
|||||||
//To display border
|
//To display border
|
||||||
void updateShadow();
|
void updateShadow();
|
||||||
void setBackground(const ImagePath & filename);
|
void setBackground(const ImagePath & filename);
|
||||||
|
std::shared_ptr<CPicture> createBg(const ImagePath & imageName, bool playerColored);
|
||||||
public:
|
public:
|
||||||
enum EOptions
|
enum EOptions
|
||||||
{
|
{
|
||||||
|
Loading…
Reference in New Issue
Block a user