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

bulk move to altar

This commit is contained in:
SoundSSGood 2024-01-16 16:22:40 +02:00
parent 652f009181
commit f66918ea14
6 changed files with 128 additions and 120 deletions

View File

@ -12,7 +12,6 @@
#include "CAltarArtifacts.h" #include "CAltarArtifacts.h"
#include "../../gui/CGuiHandler.h" #include "../../gui/CGuiHandler.h"
#include "../../gui/CursorHandler.h"
#include "../../widgets/Buttons.h" #include "../../widgets/Buttons.h"
#include "../../widgets/TextControls.h" #include "../../widgets/TextControls.h"
@ -51,8 +50,8 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance *
CGI->generaltexth->zelp[570], std::bind(&CAltarArtifacts::sacrificeBackpack, this)); CGI->generaltexth->zelp[570], std::bind(&CAltarArtifacts::sacrificeBackpack, this));
sacrificeBackpackButton->block(hero->artifactsInBackpack.empty()); sacrificeBackpackButton->block(hero->artifactsInBackpack.empty());
arts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -11)); heroArts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -11));
arts->setHero(hero); heroArts->setHero(hero);
int slotNum = 0; int slotNum = 0;
for(auto & altarSlotPos : posSlotsAltar) for(auto & altarSlotPos : posSlotsAltar)
@ -70,32 +69,25 @@ CAltarArtifacts::CAltarArtifacts(const IMarket * market, const CGHeroInstance *
TExpType CAltarArtifacts::calcExpAltarForHero() TExpType CAltarArtifacts::calcExpAltarForHero()
{ {
auto artifactsOfHero = std::dynamic_pointer_cast<CArtifactsOfHeroAltar>(arts);
TExpType expOnAltar(0); TExpType expOnAltar(0);
for(const auto art : artifactsOfHero->artifactsOnAltar) for(const auto & tradeSlot : tradeSlotsMap)
{ expOnAltar += calcExpCost(tradeSlot.first);
int dmp = 0; expForHero->setText(std::to_string(expOnAltar));
int expOfArt = 0; return expOnAltar;
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() void CAltarArtifacts::makeDeal()
{ {
std::vector<TradeItemSell> positions; std::vector<TradeItemSell> positions;
for(const auto art : arts->artifactsOnAltar) for(const auto art : tradeSlotsMap)
{ {
positions.push_back(hero->getSlotByInstance(art)); positions.push_back(hero->getSlotByInstance(art.first));
} }
std::sort(positions.begin(), positions.end()); std::sort(positions.begin(), positions.end());
std::reverse(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); LOCPLINT->cb->trade(market, EMarketMode::ARTIFACT_EXP, positions, std::vector<TradeItemBuy>(), std::vector<ui32>(), hero);
arts->artifactsOnAltar.clear(); heroArts->artifactsOnAltar.clear();
for(auto item : items[0]) for(auto item : items[0])
{ {
@ -108,37 +100,19 @@ void CAltarArtifacts::makeDeal()
void CAltarArtifacts::sacrificeAll() void CAltarArtifacts::sacrificeAll()
{ {
std::vector<ConstTransitivePtr<CArtifactInstance>> artsForMove; LOCPLINT->cb->bulkMoveArtifacts(heroArts->getHero()->id, altarId, false, true, true);
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() void CAltarArtifacts::sacrificeBackpack()
{ {
/*while (!arts->visibleArtSet.artifactsInBackpack.empty()) LOCPLINT->cb->bulkMoveArtifacts(heroArts->getHero()->id, altarId, false, false, true);
{
if(!putArtOnAltar(nullptr, arts->visibleArtSet.artifactsInBackpack[0].artifact))
break;
};*/
calcExpAltarForHero();
} }
void CAltarArtifacts::setSelectedArtifact(const CArtifactInstance * art) void CAltarArtifacts::setSelectedArtifact(const CArtifactInstance * art)
{ {
if(art) if(art)
{ {
selectedArt->setArtifact(art); selectedCost->setText(std::to_string(calcExpCost(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 else
{ {
@ -147,75 +121,98 @@ void CAltarArtifacts::setSelectedArtifact(const CArtifactInstance * art)
} }
} }
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 std::shared_ptr<CArtifactsOfHeroAltar> CAltarArtifacts::getAOHset() const
{ {
return arts; return heroArts;
} }
bool CAltarArtifacts::putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art) ObjectInstanceID CAltarArtifacts::getObjId() const
{ {
if(!art->artType->isTradable()) return altarId;
}
void CAltarArtifacts::updateSlots()
{
assert(altarArtifacts->artifactsInBackpack.size() <= 22);
assert(tradeSlotsMap.size() <= 22);
auto slotsToAdd = tradeSlotsMap;
for(auto & altarSlot : items[0])
{ {
logGlobal->warn("Cannot put special artifact on altar!"); if(altarSlot->id != -1)
return false; if(tradeSlotsMap.find(altarSlot->getArtInstance()) == tradeSlotsMap.end())
{
altarSlot->setID(-1);
altarSlot->subtitle.clear();
}
else
{
slotsToAdd.erase(altarSlot->getArtInstance());
}
} }
if(!altarSlot || altarSlot->id != -1) for(auto & tradeSlot : slotsToAdd)
{ {
int slotIndex = -1; assert(tradeSlot.second->id == -1);
while(items[0][++slotIndex]->id >= 0 && slotIndex + 1 < items[0].size()); assert(altarArtifacts->getSlotByInstance(tradeSlot.first) != ArtifactPosition::PRE_FIRST);
slotIndex = items[0][slotIndex]->id == -1 ? slotIndex : -1; tradeSlot.second->setArtInstance(tradeSlot.first);
if(slotIndex < 0) tradeSlot.second->subtitle = std::to_string(calcExpCost(tradeSlot.first));
}
for(auto & slotInfo : altarArtifacts->artifactsInBackpack)
{
if(tradeSlotsMap.find(slotInfo.artifact) == tradeSlotsMap.end())
{ {
logGlobal->warn("No free slots on altar!"); for(auto & altarSlot : items[0])
return false; if(altarSlot->id == -1)
{
altarSlot->setArtInstance(slotInfo.artifact);
altarSlot->subtitle = std::to_string(calcExpCost(slotInfo.artifact));
tradeSlotsMap.emplace(slotInfo.artifact, altarSlot);
break;
}
} }
altarSlot = items[0][slotIndex];
} }
calcExpAltarForHero();
deal->block(tradeSlotsMap.empty());
}
int dmp = 0; void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> & altarSlot, std::shared_ptr<CTradeableItem> & hCurSlot)
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)
{ {
if(const auto pickedArtInst = arts->getPickedArtifact()) assert(altarSlot);
if(const auto pickedArtInst = heroArts->getPickedArtifact())
{ {
if(pickedArtInst->canBePutAt(altarArtifacts)) if(pickedArtInst->canBePutAt(altarArtifacts))
{ if(pickedArtInst->artType->isTradable())
LOCPLINT->cb->swapArtifacts(ArtifactLocation(arts->getHero()->id, ArtifactPosition::TRANSITION_POS), {
ArtifactLocation(altarId, ArtifactPosition::ALTAR)); if(altarSlot->id == -1)
moveArtToAltar(newSlot, pickedArtInst); tradeSlotsMap.emplace(pickedArtInst, altarSlot);
} heroArts->artifactsOnAltar.insert(pickedArtInst);
deal->block(false);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(heroArts->getHero()->id, ArtifactPosition::TRANSITION_POS),
ArtifactLocation(altarId, ArtifactPosition::ALTAR));
}
else
{
logGlobal->warn("Cannot put special artifact on altar!");
return;
}
} }
else if(const CArtifactInstance * art = newSlot->getArtInstance()) else if(const CArtifactInstance * art = altarSlot->getArtInstance())
{ {
const auto slot = altarArtifacts->getSlotByInstance(art); const auto slot = altarArtifacts->getSlotByInstance(art);
assert(slot != ArtifactPosition::PRE_FIRST); assert(slot != ArtifactPosition::PRE_FIRST);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot), LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot), ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS));
ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS)); heroArts->artifactsOnAltar.erase(art);
arts->artifactsOnAltar.erase(art); tradeSlotsMap.erase(art);
newSlot->setID(-1);
newSlot->subtitle.clear();
deal->block(!arts->artifactsOnAltar.size());
} }
calcExpAltarForHero(); }
TExpType CAltarArtifacts::calcExpCost(const CArtifactInstance* art)
{
int dmp = 0;
int expOfArt = 0;
market->getOffer(art->getTypeId(), 0, dmp, expOfArt, EMarketMode::ARTIFACT_EXP);
return hero->calculateXp(expOfArt);
} }

View File

@ -21,8 +21,9 @@ public:
void sacrificeAll() override; void sacrificeAll() override;
void sacrificeBackpack(); void sacrificeBackpack();
void setSelectedArtifact(const CArtifactInstance * art); void setSelectedArtifact(const CArtifactInstance * art);
void moveArtToAltar(std::shared_ptr<CTradeableItem>, const CArtifactInstance * art);
std::shared_ptr<CArtifactsOfHeroAltar> getAOHset() const; std::shared_ptr<CArtifactsOfHeroAltar> getAOHset() const;
ObjectInstanceID getObjId() const;
void updateSlots();
private: private:
ObjectInstanceID altarId; ObjectInstanceID altarId;
@ -30,7 +31,8 @@ private:
std::shared_ptr<CArtPlace> selectedArt; std::shared_ptr<CArtPlace> selectedArt;
std::shared_ptr<CLabel> selectedCost; std::shared_ptr<CLabel> selectedCost;
std::shared_ptr<CButton> sacrificeBackpackButton; std::shared_ptr<CButton> sacrificeBackpackButton;
std::shared_ptr<CArtifactsOfHeroAltar> arts; std::shared_ptr<CArtifactsOfHeroAltar> heroArts;
std::map<const CArtifactInstance*, std::shared_ptr<CTradeableItem>> tradeSlotsMap;
const std::vector<Point> posSlotsAltar = const std::vector<Point> posSlotsAltar =
{ {
@ -44,6 +46,6 @@ private:
Point(452, 333) Point(452, 333)
}; };
bool putArtOnAltar(std::shared_ptr<CTradeableItem> altarSlot, const CArtifactInstance * art); void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & altarSlot, std::shared_ptr<CTradeableItem> & hCurSlot) override;
void onSlotClickPressed(const std::shared_ptr<CTradeableItem> & newSlot, std::shared_ptr<CTradeableItem> & hCurSlot) override; TExpType calcExpCost(const CArtifactInstance * art);
}; };

View File

@ -19,6 +19,7 @@
#include "../CGameInfo.h" #include "../CGameInfo.h"
#include "../lib/networkPacks/ArtifactLocation.h"
#include "../../lib/CGeneralTextHandler.h" #include "../../lib/CGeneralTextHandler.h"
#include "../../lib/CHeroHandler.h" #include "../../lib/CHeroHandler.h"
#include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/mapObjects/CGHeroInstance.h"
@ -115,6 +116,9 @@ void CAltarWindow::artifactMoved(const ArtifactLocation & srcLoc, const Artifact
if(auto altarArtifacts = std::static_pointer_cast<CAltarArtifacts>(altar)) if(auto altarArtifacts = std::static_pointer_cast<CAltarArtifacts>(altar))
{ {
if(srcLoc.artHolder == altarArtifacts->getObjId() || destLoc.artHolder == altarArtifacts->getObjId())
altarArtifacts->updateSlots();
if(const auto pickedArt = getPickedArtifact()) if(const auto pickedArt = getPickedArtifact())
altarArtifacts->setSelectedArtifact(pickedArt); altarArtifacts->setSelectedArtifact(pickedArt);
else else

View File

@ -2767,27 +2767,26 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
return true; return true;
} }
bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack) bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack)
{ {
// Make sure exchange is even possible between the two heroes. // Make sure exchange is even possible between the two heroes.
if(!isAllowedExchange(srcHero, dstHero)) if(!isAllowedExchange(srcId, dstId))
COMPLAIN_RET("That heroes cannot make any exchange!"); COMPLAIN_RET("That heroes cannot make any exchange!");
auto psrcHero = getHero(srcHero); auto psrcSet = getArtSet(srcId);
auto pdstHero = getHero(dstHero); auto pdstSet = getArtSet(dstId);
if((!psrcHero) || (!pdstHero)) if((!psrcSet) || (!pdstSet))
COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID"); COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID");
BulkMoveArtifacts ma(srcHero, dstHero, swap); BulkMoveArtifacts ma(srcId, dstId, swap);
auto & slotsSrcDst = ma.artsPack0; auto & slotsSrcDst = ma.artsPack0;
auto & slotsDstSrc = ma.artsPack1; auto & slotsDstSrc = ma.artsPack1;
// Temporary fitting set for artifacts. Used to select available slots before sending data. // Temporary fitting set for artifacts. Used to select available slots before sending data.
CArtifactFittingSet artFittingSet(pdstHero->bearerType()); CArtifactFittingSet artFittingSet(pdstSet->bearerType());
auto moveArtifact = [this, &artFittingSet](const CArtifactInstance * artifact, auto moveArtifact = [this, &artFittingSet, dstId](const CArtifactInstance * artifact,
ArtifactPosition srcSlot, const CGHeroInstance * dstHero, ArtifactPosition srcSlot, std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
{ {
assert(artifact); assert(artifact);
auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, artifact->getTypeId()); auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, artifact->getTypeId());
@ -2796,20 +2795,23 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact)); artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact));
slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact->getTypeId(), dstSlot)) // TODO Shouldn't be here. Possibly in callback after equipping the artifact
giveHeroNewArtifact(dstHero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK); if(auto dstHero = getHero(dstId))
{
if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, artifact->getTypeId(), dstSlot))
giveHeroNewArtifact(dstHero, ArtifactID(ArtifactID::SPELLBOOK).toArtifact(), ArtifactPosition::SPELLBOOK);
}
} }
}; };
if(swap) if(swap)
{ {
auto moveArtsWorn = [moveArtifact](const CGHeroInstance * srcHero, const CGHeroInstance * dstHero, auto moveArtsWorn = [moveArtifact](const CArtifactSet * srcArtSet, std::vector<BulkMoveArtifacts::LinkedSlots> & slots)
std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
{ {
for(auto & artifact : srcHero->artifactsWorn) for(auto & artifact : srcArtSet->artifactsWorn)
{ {
if(ArtifactUtils::isArtRemovable(artifact)) if(ArtifactUtils::isArtRemovable(artifact))
moveArtifact(artifact.second.getArt(), artifact.first, dstHero, slots); moveArtifact(artifact.second.getArt(), artifact.first, slots);
} }
}; };
auto moveArtsInBackpack = [](const CArtifactSet * artSet, auto moveArtsInBackpack = [](const CArtifactSet * artSet,
@ -2824,41 +2826,41 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
if(equipped) if(equipped)
{ {
// Move over artifacts that are worn srcHero -> dstHero // Move over artifacts that are worn srcHero -> dstHero
moveArtsWorn(psrcHero, pdstHero, slotsSrcDst); moveArtsWorn(psrcSet, slotsSrcDst);
artFittingSet.artifactsWorn.clear(); artFittingSet.artifactsWorn.clear();
// Move over artifacts that are worn dstHero -> srcHero // Move over artifacts that are worn dstHero -> srcHero
moveArtsWorn(pdstHero, psrcHero, slotsDstSrc); moveArtsWorn(pdstSet, slotsDstSrc);
} }
if(backpack) if(backpack)
{ {
// Move over artifacts that are in backpack srcHero -> dstHero // Move over artifacts that are in backpack srcHero -> dstHero
moveArtsInBackpack(psrcHero, slotsSrcDst); moveArtsInBackpack(psrcSet, slotsSrcDst);
// Move over artifacts that are in backpack dstHero -> srcHero // Move over artifacts that are in backpack dstHero -> srcHero
moveArtsInBackpack(pdstHero, slotsDstSrc); moveArtsInBackpack(pdstSet, slotsDstSrc);
} }
} }
else else
{ {
artFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack; artFittingSet.artifactsInBackpack = pdstSet->artifactsInBackpack;
artFittingSet.artifactsWorn = pdstHero->artifactsWorn; artFittingSet.artifactsWorn = pdstSet->artifactsWorn;
if(equipped) if(equipped)
{ {
// Move over artifacts that are worn // Move over artifacts that are worn
for(auto & artInfo : psrcHero->artifactsWorn) for(auto & artInfo : psrcSet->artifactsWorn)
{ {
if(ArtifactUtils::isArtRemovable(artInfo)) if(ArtifactUtils::isArtRemovable(artInfo))
{ {
moveArtifact(psrcHero->getArt(artInfo.first), artInfo.first, pdstHero, slotsSrcDst); moveArtifact(psrcSet->getArt(artInfo.first), artInfo.first, slotsSrcDst);
} }
} }
} }
if(backpack) if(backpack)
{ {
// Move over artifacts that are in backpack // Move over artifacts that are in backpack
for(auto & slotInfo : psrcHero->artifactsInBackpack) for(auto & slotInfo : psrcSet->artifactsInBackpack)
{ {
moveArtifact(psrcHero->getArt(psrcHero->getArtPos(slotInfo.artifact)), moveArtifact(psrcSet->getArt(psrcSet->getArtPos(slotInfo.artifact)),
psrcHero->getArtPos(slotInfo.artifact), pdstHero, slotsSrcDst); psrcSet->getArtPos(slotInfo.artifact), slotsSrcDst);
} }
} }
} }

View File

@ -130,7 +130,7 @@ public:
bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override; bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override;
void removeArtifact(const ArtifactLocation &al) override; void removeArtifact(const ArtifactLocation &al) override;
bool moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst) override; bool moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst) override;
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack); bool bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack);
bool eraseArtifactByClient(const ArtifactLocation & al); bool eraseArtifactByClient(const ArtifactLocation & al);
void synchronizeArtifactHandlerLists(); void synchronizeArtifactHandlerLists();

View File

@ -200,6 +200,9 @@ bool OpenWindowQuery::blocksPack(const CPack *pack) const
if(dynamic_ptr_cast<ExchangeArtifacts>(pack) != nullptr) if(dynamic_ptr_cast<ExchangeArtifacts>(pack) != nullptr)
return false; return false;
if(dynamic_ptr_cast<BulkExchangeArtifacts>(pack) != nullptr)
return false;
if(dynamic_ptr_cast<AssembleArtifacts>(pack)) if(dynamic_ptr_cast<AssembleArtifacts>(pack))
return false; return false;