From 5dbe88d9a4e309e8fd4002e49dcb66e3231aef99 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 28 Mar 2024 00:28:31 +0200 Subject: [PATCH 1/6] End of battle BulkMoveArtifacts --- client/NetPacksClient.cpp | 4 +- lib/CArtHandler.cpp | 6 +- lib/CArtHandler.h | 2 +- lib/networkPacks/ArtifactLocation.h | 6 ++ server/CGameHandler.cpp | 2 +- server/battles/BattleResultProcessor.cpp | 103 +++++++++-------------- 6 files changed, 55 insertions(+), 68 deletions(-) diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 083df1c71..20b78e4bb 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -306,8 +306,8 @@ void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack) }; moveArtifact(pack.interfaceOwner); - if(pack.interfaceOwner != cl.getOwner(pack.dst.artHolder)) - moveArtifact(cl.getOwner(pack.dst.artHolder)); + //if(pack.interfaceOwner != cl.getOwner(pack.dst.artHolder)) + // moveArtifact(cl.getOwner(pack.dst.artHolder)); cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings } diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 1c0467d4a..84958e070 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -1079,8 +1079,8 @@ void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const Artifa } } -CArtifactFittingSet::CArtifactFittingSet(ArtBearer::ArtBearer Bearer): - Bearer(Bearer) +CArtifactFittingSet::CArtifactFittingSet(ArtBearer::ArtBearer bearer) + : bearer(bearer) { } @@ -1094,7 +1094,7 @@ CArtifactFittingSet::CArtifactFittingSet(const CArtifactSet & artSet) ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const { - return this->Bearer; + return this->bearer; } VCMI_LIB_NAMESPACE_END diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 124713299..435a02bae 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -255,7 +255,7 @@ public: ArtBearer::ArtBearer bearerType() const override; protected: - ArtBearer::ArtBearer Bearer; + ArtBearer::ArtBearer bearer; }; VCMI_LIB_NAMESPACE_END diff --git a/lib/networkPacks/ArtifactLocation.h b/lib/networkPacks/ArtifactLocation.h index 42739083f..3864ebad3 100644 --- a/lib/networkPacks/ArtifactLocation.h +++ b/lib/networkPacks/ArtifactLocation.h @@ -37,6 +37,12 @@ struct ArtifactLocation , creature(creatureSlot) { } + ArtifactLocation(const ObjectInstanceID id, const std::optional creatureSlot, const ArtifactPosition & slot) + : artHolder(id) + , slot(slot) + , creature(creatureSlot) + { + } template void serialize(Handler & h) { diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index b8169b9b6..0a1b995a5 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2891,7 +2891,7 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI bool CGameHandler::scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left) { - auto artSet = getArtSet(heroID); + const auto artSet = getArtSet(heroID); COMPLAIN_RET_FALSE_IF(artSet == nullptr, "scrollBackpackArtifacts: wrong hero's ID"); BulkMoveArtifacts bma(player, heroID, heroID, false); diff --git a/server/battles/BattleResultProcessor.cpp b/server/battles/BattleResultProcessor.cpp index 7416094ec..4fc64182f 100644 --- a/server/battles/BattleResultProcessor.cpp +++ b/server/battles/BattleResultProcessor.cpp @@ -342,80 +342,61 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) if(result == EBattleResult::NORMAL && !finishingBattle->isDraw() && finishingBattle->winnerHero) { - auto sendMoveArtifact = [&](const CArtifactInstance *art, MoveArtifact *ma) + BulkMoveArtifacts bma(finishingBattle->winnerHero->getOwner(), finishingBattle->loserHero->id, finishingBattle->winnerHero->id, false); + bma.askAssemble = true; + CArtifactFittingSet artFittingSet(*finishingBattle->winnerHero); + + const auto addArtifactToTransfer = [&](const ArtifactPosition & srcSlot, const CArtifactInstance * art) { - const auto slot = ArtifactUtils::getArtAnyPosition(finishingBattle->winnerHero, art->getTypeId()); - if(slot != ArtifactPosition::PRE_FIRST) + const auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, art->getTypeId()); + if(dstSlot != ArtifactPosition::PRE_FIRST) { - arts.push_back(art); - ma->dst = ArtifactLocation(finishingBattle->winnerHero->id, slot); - if(ArtifactUtils::isSlotBackpack(slot)) - ma->askAssemble = false; - gameHandler->sendAndApply(ma); + bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); + arts.emplace_back(art); + artFittingSet.putArtifact(dstSlot, const_cast(art)); } }; - - if (finishingBattle->loserHero) + const auto sendArtifacts = [&bma, this]() { - //TODO: wrap it into a function, somehow (std::variant -_-) - auto artifactsWorn = finishingBattle->loserHero->artifactsWorn; - for (auto artSlot : artifactsWorn) + if(!bma.artsPack0.empty()) + gameHandler->sendAndApply(&bma); + }; + + if(finishingBattle->loserHero) + { + for(const auto & artSlot : finishingBattle->loserHero->artifactsWorn) { - MoveArtifact ma; - ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first); - const CArtifactInstance * art = finishingBattle->loserHero->getArt(artSlot.first); - if (art && !art->artType->isBig() && - art->artType->getId() != ArtifactID::SPELLBOOK) - // don't move war machines or locked arts (spellbook) - { - sendMoveArtifact(art, &ma); - } + if(ArtifactUtils::isArtRemovable(artSlot)) + addArtifactToTransfer(artSlot.first, artSlot.second.getArt()); } - for(int slotNumber = finishingBattle->loserHero->artifactsInBackpack.size() - 1; slotNumber >= 0; slotNumber--) + for(const auto & artSlot : finishingBattle->loserHero->artifactsInBackpack) { - //we assume that no big artifacts can be found - MoveArtifact ma; - ma.src = ArtifactLocation(finishingBattle->loserHero->id, - ArtifactPosition(ArtifactPosition::BACKPACK_START + slotNumber)); //backpack automatically shifts arts to beginning - const CArtifactInstance * art = finishingBattle->loserHero->getArt(ArtifactPosition::BACKPACK_START + slotNumber); - if (art->artType->getId() != ArtifactID::GRAIL) //grail may not be won - { - sendMoveArtifact(art, &ma); - } + const auto art = artSlot.getArt(); + if(art->getTypeId() != ArtifactID::GRAIL) + addArtifactToTransfer(finishingBattle->loserHero->getArtPos(art), art); } - if (finishingBattle->loserHero->commander) //TODO: what if commanders belong to no hero? + sendArtifacts(); + + bma.askAssemble = false; + bma.artsPack0.clear(); + if(finishingBattle->loserHero->commander) { - artifactsWorn = finishingBattle->loserHero->commander->artifactsWorn; - for (auto artSlot : artifactsWorn) - { - MoveArtifact ma; - ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first); - ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander); - const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first); - if (art && !art->artType->isBig()) - { - sendMoveArtifact(art, &ma); - } - } + bma.srcCreature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander); + for(const auto & artSlot : finishingBattle->loserHero->commander->artifactsWorn) + addArtifactToTransfer(artSlot.first, artSlot.second.getArt()); + sendArtifacts(); } } - - auto loser = battle.otherSide(battleResult->winner); - - for (auto armySlot : battle.battleGetArmyObject(loser)->stacks) + auto armyObj = battle.battleGetArmyObject(battle.otherSide(battleResult->winner)); + bma.srcArtHolder = armyObj->id; + for(const auto & armySlot : armyObj->stacks) { - auto artifactsWorn = armySlot.second->artifactsWorn; - for(const auto & artSlot : artifactsWorn) - { - MoveArtifact ma; - ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first); - ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander); - const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first); - if (art && !art->artType->isBig()) - { - sendMoveArtifact(art, &ma); - } - } + bma.artsPack0.clear(); + bma.interfaceOwner = finishingBattle->winnerHero->getOwner(); + bma.srcCreature = armySlot.first; + for(const auto & artSlot : armySlot.second->artifactsWorn) + addArtifactToTransfer(artSlot.first, armySlot.second->getArt(artSlot.first)); + sendArtifacts(); } } From 6dd76908bc28a1c6ba2d188d62aee54de294f30e Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 28 Mar 2024 16:16:10 +0200 Subject: [PATCH 2/6] MoveArtifact struct not used now --- client/ClientNetPackVisitors.h | 1 - client/NetPacksClient.cpp | 42 +++++++------------- client/widgets/CArtifactsOfHeroBackpack.cpp | 4 +- client/widgets/markets/CAltarArtifacts.cpp | 2 +- lib/CArtHandler.cpp | 15 +------ lib/CArtHandler.h | 3 +- lib/IGameCallback.cpp | 4 ++ lib/constants/NumericConstants.h | 1 + lib/networkPacks/NetPackVisitor.h | 1 - lib/networkPacks/NetPacksLib.cpp | 18 +-------- lib/networkPacks/PacksForClient.h | 24 ----------- lib/registerTypes/RegisterTypesClientPacks.h | 1 - server/CGameHandler.cpp | 4 +- server/battles/BattleResultProcessor.cpp | 24 +++++------ 14 files changed, 38 insertions(+), 106 deletions(-) diff --git a/client/ClientNetPackVisitors.h b/client/ClientNetPackVisitors.h index 51812dedc..5940da3b4 100644 --- a/client/ClientNetPackVisitors.h +++ b/client/ClientNetPackVisitors.h @@ -48,7 +48,6 @@ public: void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) override; void visitPutArtifact(PutArtifact & pack) override; void visitEraseArtifact(EraseArtifact & pack) override; - void visitMoveArtifact(MoveArtifact & pack) override; void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) override; void visitAssembledArtifact(AssembledArtifact & pack) override; void visitDisassembledArtifact(DisassembledArtifact & pack) override; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 20b78e4bb..8678d987c 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -296,41 +296,29 @@ void ApplyClientNetPackVisitor::visitEraseArtifact(EraseArtifact & pack) callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactRemoved, pack.al); } -void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack) -{ - auto moveArtifact = [this, &pack](PlayerColor player) -> void - { - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::artifactMoved, pack.src, pack.dst); - if(pack.askAssemble) - callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst); - }; - - moveArtifact(pack.interfaceOwner); - //if(pack.interfaceOwner != cl.getOwner(pack.dst.artHolder)) - // moveArtifact(cl.getOwner(pack.dst.artHolder)); - - cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings -} - void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack) { - auto applyMove = [this, &pack](std::vector & artsPack) -> void + const auto dstOwner = cl.getOwner(pack.dstArtHolder); + const auto applyMove = [this, &pack, dstOwner](std::vector & artsPack) { - for(auto & slotToMove : artsPack) + for(const auto & slotToMove : artsPack) { - auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos); - auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos); - MoveArtifact ma(pack.interfaceOwner, srcLoc, dstLoc, pack.askAssemble); - visitMoveArtifact(ma); + const auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos); + const auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos); + + callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); + if(pack.askAssemble) + callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::askToAssembleArtifact, dstLoc); + if(pack.interfaceOwner != dstOwner) + callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); + + cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings } }; - auto srcOwner = cl.getOwner(pack.srcArtHolder); - auto dstOwner = cl.getOwner(pack.dstArtHolder); - // Begin a session of bulk movement of arts. It is not necessary but useful for the client optimization. - callInterfaceIfPresent(cl, srcOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size()); - if(srcOwner != dstOwner) + callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size()); + if(pack.interfaceOwner != dstOwner) callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size()); applyMove(pack.artsPack0); diff --git a/client/widgets/CArtifactsOfHeroBackpack.cpp b/client/widgets/CArtifactsOfHeroBackpack.cpp index 3a33e35e3..06e926d97 100644 --- a/client/widgets/CArtifactsOfHeroBackpack.cpp +++ b/client/widgets/CArtifactsOfHeroBackpack.cpp @@ -176,9 +176,9 @@ void CArtifactsOfHeroQuickBackpack::setHero(const CGHeroInstance * hero) initAOHbackpack(requiredSlots, false); auto artPlace = backpack.begin(); for(auto & art : filteredArts) - setSlotData(*artPlace++, curHero->getSlotByInstance(art.second)); + setSlotData(*artPlace++, curHero->getArtPos(art.second)); for(auto & art : filteredScrolls) - setSlotData(*artPlace++, curHero->getSlotByInstance(art.second)); + setSlotData(*artPlace++, curHero->getArtPos(art.second)); } } diff --git a/client/widgets/markets/CAltarArtifacts.cpp b/client/widgets/markets/CAltarArtifacts.cpp index 240282816..bf4b57ad2 100644 --- a/client/widgets/markets/CAltarArtifacts.cpp +++ b/client/widgets/markets/CAltarArtifacts.cpp @@ -221,7 +221,7 @@ void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr & else if(altarSlot->id != -1) { assert(tradeSlotsMap.at(altarSlot)); - const auto slot = altarArtifacts->getSlotByInstance(tradeSlotsMap.at(altarSlot)); + const auto slot = altarArtifacts->getArtPos(tradeSlotsMap.at(altarSlot)); assert(slot != ArtifactPosition::PRE_FIRST); LOCPLINT->cb->swapArtifacts(ArtifactLocation(heroArts->altarId, slot), ArtifactLocation(hero->id, GH.isKeyboardCtrlDown() ? ArtifactPosition::FIRST_AVAILABLE : ArtifactPosition::TRANSITION_POS)); diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 84958e070..a15ad071d 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -741,19 +741,6 @@ std::vector CArtifactSet::getBackpackArtPositions(const Artifa return result; } -ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance *art) const -{ - for(auto i : artifactsWorn) - if(i.second.artifact == art) - return i.first; - - for(int i = 0; i < artifactsInBackpack.size(); i++) - if(artifactsInBackpack[i].artifact == art) - return ArtifactPosition::BACKPACK_START + i; - - return ArtifactPosition::PRE_FIRST; -} - const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanceID & artInstId) const { for(auto i : artifactsWorn) @@ -767,7 +754,7 @@ const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanc return nullptr; } -const ArtifactPosition CArtifactSet::getSlotByInstance(const CArtifactInstance * artInst) const +const ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance * artInst) const { if(artInst) { diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 435a02bae..bd57aa59e 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -207,11 +207,10 @@ public: /// Looks for equipped artifact with given ID and returns its slot ID or -1 if none /// (if more than one such artifact lower ID is returned) ArtifactPosition getArtPos(const ArtifactID & aid, bool onlyWorn = true, bool allowLocked = true) const; - ArtifactPosition getArtPos(const CArtifactInstance *art) const; + const ArtifactPosition getArtPos(const CArtifactInstance * art) const; std::vector getAllArtPositions(const ArtifactID & aid, bool onlyWorn, bool allowLocked, bool getAll) const; std::vector getBackpackArtPositions(const ArtifactID & aid) const; const CArtifactInstance * getArtByInstanceId(const ArtifactInstanceID & artInstId) const; - const ArtifactPosition getSlotByInstance(const CArtifactInstance * artInst) const; /// Search for constituents of assemblies in backpack which do not have an ArtifactPosition const CArtifactInstance * getHiddenArt(const ArtifactID & aid) const; const CArtifactInstance * getAssemblyByConstituent(const ArtifactID & aid) const; diff --git a/lib/IGameCallback.cpp b/lib/IGameCallback.cpp index 866a1b441..acef3ca0f 100644 --- a/lib/IGameCallback.cpp +++ b/lib/IGameCallback.cpp @@ -284,6 +284,10 @@ CArtifactSet * CNonConstInfoCallback::getArtSet(const ArtifactLocation & loc) return hero; } } + else if(auto army = getArmyInstance(loc.artHolder)) + { + return army->getStackPtr(loc.creature.value()); + } else if(auto market = dynamic_cast(getObjInstance(loc.artHolder))) { return market; diff --git a/lib/constants/NumericConstants.h b/lib/constants/NumericConstants.h index b0cda4270..1e3693649 100644 --- a/lib/constants/NumericConstants.h +++ b/lib/constants/NumericConstants.h @@ -54,6 +54,7 @@ namespace GameConstants constexpr int ALTAR_ARTIFACTS_SLOTS = 22; constexpr int TOURNAMENT_RULES_DD_MAP_TILES_THRESHOLD = 144*144*2; //map tiles count threshold for 2 dimension door casts with tournament rules constexpr int KINGDOM_WINDOW_HEROES_SLOTS = 4; + constexpr int INFO_WINDOW_ARTIFACTS_MAX_ITEMS = 14; } VCMI_LIB_NAMESPACE_END diff --git a/lib/networkPacks/NetPackVisitor.h b/lib/networkPacks/NetPackVisitor.h index 02e2d287f..73d3d8d04 100644 --- a/lib/networkPacks/NetPackVisitor.h +++ b/lib/networkPacks/NetPackVisitor.h @@ -78,7 +78,6 @@ public: virtual void visitBulkSmartRebalanceStacks(BulkSmartRebalanceStacks & pack) {} virtual void visitPutArtifact(PutArtifact & pack) {} virtual void visitEraseArtifact(EraseArtifact & pack) {} - virtual void visitMoveArtifact(MoveArtifact & pack) {} virtual void visitBulkMoveArtifacts(BulkMoveArtifacts & pack) {} virtual void visitAssembledArtifact(AssembledArtifact & pack) {} virtual void visitDisassembledArtifact(DisassembledArtifact & pack) {} diff --git a/lib/networkPacks/NetPacksLib.cpp b/lib/networkPacks/NetPacksLib.cpp index 2f8813a1a..6eb8f7fad 100644 --- a/lib/networkPacks/NetPacksLib.cpp +++ b/lib/networkPacks/NetPacksLib.cpp @@ -338,11 +338,6 @@ void EraseArtifact::visitTyped(ICPackVisitor & visitor) visitor.visitEraseArtifact(*this); } -void MoveArtifact::visitTyped(ICPackVisitor & visitor) -{ - visitor.visitMoveArtifact(*this); -} - void BulkMoveArtifacts::visitTyped(ICPackVisitor & visitor) { visitor.visitBulkMoveArtifacts(*this); @@ -1794,17 +1789,6 @@ void EraseArtifact::applyGs(CGameState *gs) art->removeFrom(*artSet, al.slot); } -void MoveArtifact::applyGs(CGameState * gs) -{ - auto srcHero = gs->getArtSet(src); - auto dstHero = gs->getArtSet(dst); - assert(srcHero); - assert(dstHero); - auto art = srcHero->getArt(src.slot); - assert(art && art->canBePutAt(dstHero, dst.slot)); - art->move(*srcHero, src.slot, *dstHero, dst.slot); -} - void BulkMoveArtifacts::applyGs(CGameState * gs) { const auto bulkArtsRemove = [](std::vector & artsPack, CArtifactSet & artSet) @@ -1861,7 +1845,7 @@ void AssembledArtifact::applyGs(CGameState *gs) return art->getId() == builtArt->getId(); })); - const auto transformedArtSlot = hero->getSlotByInstance(transformedArt); + const auto transformedArtSlot = hero->getArtPos(transformedArt); auto * combinedArt = new CArtifactInstance(builtArt); gs->map->addNewArtifactInstance(combinedArt); diff --git a/lib/networkPacks/PacksForClient.h b/lib/networkPacks/PacksForClient.h index 1b70d720a..70c3847f1 100644 --- a/lib/networkPacks/PacksForClient.h +++ b/lib/networkPacks/PacksForClient.h @@ -1025,30 +1025,6 @@ struct DLL_LINKAGE EraseArtifact : CArtifactOperationPack } }; -struct DLL_LINKAGE MoveArtifact : CArtifactOperationPack -{ - MoveArtifact() = default; - MoveArtifact(const PlayerColor & interfaceOwner, const ArtifactLocation & src, const ArtifactLocation & dst, bool askAssemble = true) - : interfaceOwner(interfaceOwner), src(src), dst(dst), askAssemble(askAssemble) - { - } - PlayerColor interfaceOwner; - ArtifactLocation src; - ArtifactLocation dst; - bool askAssemble = true; - - void applyGs(CGameState * gs); - void visitTyped(ICPackVisitor & visitor) override; - - template void serialize(Handler & h) - { - h & interfaceOwner; - h & src; - h & dst; - h & askAssemble; - } -}; - struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack { struct LinkedSlots diff --git a/lib/registerTypes/RegisterTypesClientPacks.h b/lib/registerTypes/RegisterTypesClientPacks.h index 9bb4fb30d..d989facd6 100644 --- a/lib/registerTypes/RegisterTypesClientPacks.h +++ b/lib/registerTypes/RegisterTypesClientPacks.h @@ -112,7 +112,6 @@ void registerTypesClientPacks(Serializer &s) s.template registerType(); s.template registerType(); s.template registerType(); - s.template registerType(); s.template registerType(); s.template registerType(); s.template registerType(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 0a1b995a5..27984bbc4 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2956,7 +2956,7 @@ bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const Obje { bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots { - artSet->getSlotByInstance(artFittingSet.getArt(availableArts.front())), + artSet->getArtPos(artFittingSet.getArt(availableArts.front())), artPos.first }); artFittingSet.removeArtifact(availableArts.front()); @@ -3921,7 +3921,7 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h int expToGive; m->getOffer(art->getTypeId(), 0, dmp, expToGive, EMarketMode::ARTIFACT_EXP); expSum += expToGive; - removeArtifact(ArtifactLocation(altarObj->id, altarObj->getSlotByInstance(art))); + removeArtifact(ArtifactLocation(altarObj->id, altarObj->getArtPos(art))); } else { diff --git a/server/battles/BattleResultProcessor.cpp b/server/battles/BattleResultProcessor.cpp index 4fc64182f..5e427f305 100644 --- a/server/battles/BattleResultProcessor.cpp +++ b/server/battles/BattleResultProcessor.cpp @@ -348,6 +348,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) const auto addArtifactToTransfer = [&](const ArtifactPosition & srcSlot, const CArtifactInstance * art) { + assert(art); const auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, art->getTypeId()); if(dstSlot != ArtifactPosition::PRE_FIRST) { @@ -371,8 +372,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) } for(const auto & artSlot : finishingBattle->loserHero->artifactsInBackpack) { - const auto art = artSlot.getArt(); - if(art->getTypeId() != ArtifactID::GRAIL) + if(const auto art = artSlot.getArt(); art->getTypeId() != ArtifactID::GRAIL) addArtifactToTransfer(finishingBattle->loserHero->getArtPos(art), art); } sendArtifacts(); @@ -399,31 +399,27 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) sendArtifacts(); } } - - if (arts.size()) //display loot + // Display loot + if(!arts.empty()) { InfoWindow iw; iw.player = finishingBattle->winnerHero->tempOwner; + iw.text.appendLocalString(EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact - iw.text.appendLocalString (EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact - - for (auto art : arts) //TODO; separate function to display loot for various objects? + for(auto art : arts) //TODO; separate function to display loot for various objects? { - if (art->artType->getId() == ArtifactID::SPELL_SCROLL) + if(art->isScroll()) iw.components.emplace_back(ComponentType::SPELL_SCROLL, art->getScrollSpellID()); else - iw.components.emplace_back(ComponentType::ARTIFACT, art->artType->getId()); + iw.components.emplace_back(ComponentType::ARTIFACT, art->getTypeId()); - if (iw.components.size() >= 14) + if(iw.components.size() >= GameConstants::INFO_WINDOW_ARTIFACTS_MAX_ITEMS) { gameHandler->sendAndApply(&iw); iw.components.clear(); } } - if (iw.components.size()) - { - gameHandler->sendAndApply(&iw); - } + gameHandler->sendAndApply(&iw); } //Eagle Eye secondary skill handling if (!cs.spells.empty()) From f87762bc96884fc413e5d5e346806b0fbfeda9bd Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Fri, 10 May 2024 17:57:15 +0300 Subject: [PATCH 3/6] endBattleConfirm --- client/widgets/CArtPlace.cpp | 2 +- server/battles/BattleResultProcessor.cpp | 299 ++++++++++++----------- 2 files changed, 155 insertions(+), 146 deletions(-) diff --git a/client/widgets/CArtPlace.cpp b/client/widgets/CArtPlace.cpp index 0f9e3656f..0e2b31139 100644 --- a/client/widgets/CArtPlace.cpp +++ b/client/widgets/CArtPlace.cpp @@ -263,12 +263,12 @@ bool ArtifactUtilsClient::askToAssemble(const CGHeroInstance * hero, const Artif boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex); for(const auto combinedArt : assemblyPossibilities) { + LOCPLINT->waitWhileDialog(); bool assembleConfirmed = false; CFunctionList onYesHandlers([&assembleConfirmed]() -> void {assembleConfirmed = true; }); onYesHandlers += std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combinedArt->getId()); LOCPLINT->showArtifactAssemblyDialog(art->artType, combinedArt, onYesHandlers); - LOCPLINT->waitWhileDialog(); if(assembleConfirmed) break; } diff --git a/server/battles/BattleResultProcessor.cpp b/server/battles/BattleResultProcessor.cpp index 5e427f305..b278bfbab 100644 --- a/server/battles/BattleResultProcessor.cpp +++ b/server/battles/BattleResultProcessor.cpp @@ -323,153 +323,9 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) CasualtiesAfterBattle cab1(battle, BattleSide::ATTACKER); CasualtiesAfterBattle cab2(battle, BattleSide::DEFENDER); - ChangeSpells cs; //for Eagle Eye - - if(!finishingBattle->isDraw() && finishingBattle->winnerHero) - { - if (int eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT)) - { - double eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_CHANCE); - for(auto & spellId : battle.getBattle()->getUsedSpells(battle.otherSide(battleResult->winner))) - { - auto spell = spellId.toEntity(VLC->spells()); - if(spell && spell->getLevel() <= eagleEyeLevel && !finishingBattle->winnerHero->spellbookContainsSpell(spell->getId()) && gameHandler->getRandomGenerator().nextInt(99) < eagleEyeChance) - cs.spells.insert(spell->getId()); - } - } - } - std::vector arts; //display them in window - - if(result == EBattleResult::NORMAL && !finishingBattle->isDraw() && finishingBattle->winnerHero) - { - BulkMoveArtifacts bma(finishingBattle->winnerHero->getOwner(), finishingBattle->loserHero->id, finishingBattle->winnerHero->id, false); - bma.askAssemble = true; - CArtifactFittingSet artFittingSet(*finishingBattle->winnerHero); - - const auto addArtifactToTransfer = [&](const ArtifactPosition & srcSlot, const CArtifactInstance * art) - { - assert(art); - const auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, art->getTypeId()); - if(dstSlot != ArtifactPosition::PRE_FIRST) - { - bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); - arts.emplace_back(art); - artFittingSet.putArtifact(dstSlot, const_cast(art)); - } - }; - const auto sendArtifacts = [&bma, this]() - { - if(!bma.artsPack0.empty()) - gameHandler->sendAndApply(&bma); - }; - - if(finishingBattle->loserHero) - { - for(const auto & artSlot : finishingBattle->loserHero->artifactsWorn) - { - if(ArtifactUtils::isArtRemovable(artSlot)) - addArtifactToTransfer(artSlot.first, artSlot.second.getArt()); - } - for(const auto & artSlot : finishingBattle->loserHero->artifactsInBackpack) - { - if(const auto art = artSlot.getArt(); art->getTypeId() != ArtifactID::GRAIL) - addArtifactToTransfer(finishingBattle->loserHero->getArtPos(art), art); - } - sendArtifacts(); - - bma.askAssemble = false; - bma.artsPack0.clear(); - if(finishingBattle->loserHero->commander) - { - bma.srcCreature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander); - for(const auto & artSlot : finishingBattle->loserHero->commander->artifactsWorn) - addArtifactToTransfer(artSlot.first, artSlot.second.getArt()); - sendArtifacts(); - } - } - auto armyObj = battle.battleGetArmyObject(battle.otherSide(battleResult->winner)); - bma.srcArtHolder = armyObj->id; - for(const auto & armySlot : armyObj->stacks) - { - bma.artsPack0.clear(); - bma.interfaceOwner = finishingBattle->winnerHero->getOwner(); - bma.srcCreature = armySlot.first; - for(const auto & artSlot : armySlot.second->artifactsWorn) - addArtifactToTransfer(artSlot.first, armySlot.second->getArt(artSlot.first)); - sendArtifacts(); - } - } - // Display loot - if(!arts.empty()) - { - InfoWindow iw; - iw.player = finishingBattle->winnerHero->tempOwner; - iw.text.appendLocalString(EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact - - for(auto art : arts) //TODO; separate function to display loot for various objects? - { - if(art->isScroll()) - iw.components.emplace_back(ComponentType::SPELL_SCROLL, art->getScrollSpellID()); - else - iw.components.emplace_back(ComponentType::ARTIFACT, art->getTypeId()); - - if(iw.components.size() >= GameConstants::INFO_WINDOW_ARTIFACTS_MAX_ITEMS) - { - gameHandler->sendAndApply(&iw); - iw.components.clear(); - } - } - gameHandler->sendAndApply(&iw); - } - //Eagle Eye secondary skill handling - if (!cs.spells.empty()) - { - cs.learn = 1; - cs.hid = finishingBattle->winnerHero->id; - - InfoWindow iw; - iw.player = finishingBattle->winnerHero->tempOwner; - iw.text.appendLocalString(EMetaText::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s - iw.text.replaceRawString(finishingBattle->winnerHero->getNameTranslated()); - - std::ostringstream names; - for (int i = 0; i < cs.spells.size(); i++) - { - names << "%s"; - if (i < cs.spells.size() - 2) - names << ", "; - else if (i < cs.spells.size() - 1) - names << "%s"; - } - names << "."; - - iw.text.replaceRawString(names.str()); - - auto it = cs.spells.begin(); - for (int i = 0; i < cs.spells.size(); i++, it++) - { - iw.text.replaceName(*it); - if (i == cs.spells.size() - 2) //we just added pre-last name - iw.text.replaceLocalString(EMetaText::GENERAL_TXT, 141); // " and " - iw.components.emplace_back(ComponentType::SPELL, *it); - } - gameHandler->sendAndApply(&iw); - gameHandler->sendAndApply(&cs); - } cab1.updateArmy(gameHandler); cab2.updateArmy(gameHandler); //take casualties after battle is deleted - if(finishingBattle->loserHero) //remove beaten hero - { - RemoveObject ro(finishingBattle->loserHero->id, finishingBattle->victor); - gameHandler->sendAndApply(&ro); - } - if(finishingBattle->isDraw() && finishingBattle->winnerHero) //for draw case both heroes should be removed - { - RemoveObject ro(finishingBattle->winnerHero->id, finishingBattle->loser); - gameHandler->sendAndApply(&ro); - } - if(battleResult->winner == BattleSide::DEFENDER && finishingBattle->winnerHero && finishingBattle->winnerHero->visitedTown @@ -482,6 +338,159 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) if(!finishingBattle->isDraw() && battleResult->exp[finishingBattle->winnerSide] && finishingBattle->winnerHero) gameHandler->giveExperience(finishingBattle->winnerHero, battleResult->exp[finishingBattle->winnerSide]); + // Eagle Eye handling + if(!finishingBattle->isDraw() && finishingBattle->winnerHero) + { + ChangeSpells spells; + + if(auto eagleEyeLevel = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_LEVEL_LIMIT)) + { + auto eagleEyeChance = finishingBattle->winnerHero->valOfBonuses(BonusType::LEARN_BATTLE_SPELL_CHANCE); + for(auto & spellId : battle.getBattle()->getUsedSpells(battle.otherSide(battleResult->winner))) + { + auto spell = spellId.toEntity(VLC->spells()); + if(spell + && spell->getLevel() <= eagleEyeLevel + && !finishingBattle->winnerHero->spellbookContainsSpell(spell->getId()) + && gameHandler->getRandomGenerator().nextInt(99) < eagleEyeChance) + { + spells.spells.insert(spell->getId()); + } + } + } + + if(!spells.spells.empty()) + { + spells.learn = 1; + spells.hid = finishingBattle->winnerHero->id; + + InfoWindow iw; + iw.player = finishingBattle->winnerHero->tempOwner; + iw.text.appendLocalString(EMetaText::GENERAL_TXT, 221); //Through eagle-eyed observation, %s is able to learn %s + iw.text.replaceRawString(finishingBattle->winnerHero->getNameTranslated()); + + std::ostringstream names; + for(int i = 0; i < spells.spells.size(); i++) + { + names << "%s"; + if(i < spells.spells.size() - 2) + names << ", "; + else if(i < spells.spells.size() - 1) + names << "%s"; + } + names << "."; + + iw.text.replaceRawString(names.str()); + + auto it = spells.spells.begin(); + for(int i = 0; i < spells.spells.size(); i++, it++) + { + iw.text.replaceName(*it); + if(i == spells.spells.size() - 2) //we just added pre-last name + iw.text.replaceLocalString(EMetaText::GENERAL_TXT, 141); // " and " + iw.components.emplace_back(ComponentType::SPELL, *it); + } + gameHandler->sendAndApply(&iw); + gameHandler->sendAndApply(&spells); + } + } + // Artifacts handling + if(result == EBattleResult::NORMAL && !finishingBattle->isDraw() && finishingBattle->winnerHero) + { + std::vector arts; // display them in window + CArtifactFittingSet artFittingSet(*finishingBattle->winnerHero); + + const auto addArtifactToTransfer = [&artFittingSet, &arts](BulkMoveArtifacts & pack, const ArtifactPosition & srcSlot, const CArtifactInstance * art) + { + assert(art); + const auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, art->getTypeId()); + if(dstSlot != ArtifactPosition::PRE_FIRST) + { + pack.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); + arts.emplace_back(art); + artFittingSet.putArtifact(dstSlot, const_cast(art)); + } + }; + const auto sendArtifacts = [this](BulkMoveArtifacts & bma) + { + if(!bma.artsPack0.empty()) + gameHandler->sendAndApply(&bma); + }; + + BulkMoveArtifacts packHero(finishingBattle->winnerHero->getOwner(), ObjectInstanceID::NONE, finishingBattle->winnerHero->id, false); + if(finishingBattle->loserHero) + { + packHero.srcArtHolder = finishingBattle->loserHero->id; + packHero.askAssemble = true; + for(const auto & artSlot : finishingBattle->loserHero->artifactsWorn) + { + if(ArtifactUtils::isArtRemovable(artSlot)) + addArtifactToTransfer(packHero, artSlot.first, artSlot.second.getArt()); + } + for(const auto & artSlot : finishingBattle->loserHero->artifactsInBackpack) + { + if(const auto art = artSlot.getArt(); art->getTypeId() != ArtifactID::GRAIL) + addArtifactToTransfer(packHero, finishingBattle->loserHero->getArtPos(art), art); + } + + if(finishingBattle->loserHero->commander) + { + BulkMoveArtifacts packCommander(finishingBattle->winnerHero->getOwner(), finishingBattle->loserHero->id, finishingBattle->winnerHero->id, false); + packCommander.srcCreature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander); + for(const auto & artSlot : finishingBattle->loserHero->commander->artifactsWorn) + addArtifactToTransfer(packCommander, artSlot.first, artSlot.second.getArt()); + sendArtifacts(packCommander); + } + } + auto armyObj = battle.battleGetArmyObject(battle.otherSide(battleResult->winner)); + for(const auto & armySlot : armyObj->stacks) + { + BulkMoveArtifacts packsArmy(finishingBattle->winnerHero->getOwner(), finishingBattle->loserHero->id, finishingBattle->winnerHero->id, false); + packsArmy.srcArtHolder = armyObj->id; + packsArmy.srcCreature = armySlot.first; + for(const auto & artSlot : armySlot.second->artifactsWorn) + addArtifactToTransfer(packsArmy, artSlot.first, armySlot.second->getArt(artSlot.first)); + sendArtifacts(packsArmy); + } + // Display loot + if(!arts.empty()) + { + InfoWindow iw; + iw.player = finishingBattle->winnerHero->tempOwner; + iw.text.appendLocalString(EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact + + for(auto art : arts) //TODO; separate function to display loot for various objects? + { + if(art->isScroll()) + iw.components.emplace_back(ComponentType::SPELL_SCROLL, art->getScrollSpellID()); + else + iw.components.emplace_back(ComponentType::ARTIFACT, art->getTypeId()); + + if(iw.components.size() >= GameConstants::INFO_WINDOW_ARTIFACTS_MAX_ITEMS) + { + gameHandler->sendAndApply(&iw); + iw.components.clear(); + } + } + gameHandler->sendAndApply(&iw); + } + if(!packHero.artsPack0.empty()) + sendArtifacts(packHero); + } + + // Remove beaten hero + if(finishingBattle->loserHero) + { + RemoveObject ro(finishingBattle->loserHero->id, finishingBattle->victor); + gameHandler->sendAndApply(&ro); + } + // For draw case both heroes should be removed + if(finishingBattle->isDraw() && finishingBattle->winnerHero) + { + RemoveObject ro(finishingBattle->winnerHero->id, finishingBattle->loser); + gameHandler->sendAndApply(&ro); + } + BattleResultAccepted raccepted; raccepted.battleID = battle.getBattle()->getBattleID(); raccepted.heroResult[0].army = const_cast(battle.battleGetArmyObject(BattleSide::ATTACKER)); @@ -490,7 +499,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) raccepted.heroResult[1].hero = const_cast(battle.battleGetFightingHero(BattleSide::DEFENDER)); raccepted.heroResult[0].exp = battleResult->exp[0]; raccepted.heroResult[1].exp = battleResult->exp[1]; - raccepted.winnerSide = finishingBattle->winnerSide; + raccepted.winnerSide = finishingBattle->winnerSide; gameHandler->sendAndApply(&raccepted); gameHandler->queries->popIfTop(battleQuery); From ef1fbffad4942857329fa9b2c113064f5f9b26e3 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sat, 22 Jun 2024 19:29:39 +0300 Subject: [PATCH 4/6] ArtifactsUIController class --- client/ArtifactsUIController.cpp | 142 +++++++++++++++++++++++ client/ArtifactsUIController.h | 38 ++++++ client/CMakeLists.txt | 2 + client/CPlayerInterface.cpp | 71 ++---------- client/CPlayerInterface.h | 6 +- client/NetPacksClient.cpp | 2 +- client/widgets/CArtPlace.cpp | 56 --------- client/widgets/CArtPlace.h | 6 - client/windows/CWindowWithArtifacts.cpp | 34 ++---- client/windows/CWindowWithArtifacts.h | 4 - lib/ArtifactUtils.cpp | 4 +- lib/ArtifactUtils.h | 2 +- lib/networkPacks/PacksForClient.h | 9 +- server/CGameHandler.cpp | 2 +- server/battles/BattleResultProcessor.cpp | 3 +- 15 files changed, 212 insertions(+), 169 deletions(-) create mode 100644 client/ArtifactsUIController.cpp create mode 100644 client/ArtifactsUIController.h diff --git a/client/ArtifactsUIController.cpp b/client/ArtifactsUIController.cpp new file mode 100644 index 000000000..859f350fe --- /dev/null +++ b/client/ArtifactsUIController.cpp @@ -0,0 +1,142 @@ +/* + * ArtifactsUIController.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 "ArtifactsUIController.h" +#include "CGameInfo.h" +#include "CPlayerInterface.h" + +#include "../CCallback.h" +#include "../lib/ArtifactUtils.h" +#include "../lib/CGeneralTextHandler.h" +#include "../lib/mapObjects/CGHeroInstance.h" + +#include "gui/CGuiHandler.h" +#include "gui/WindowHandler.h" +#include "widgets/CComponent.h" +#include "windows/CWindowWithArtifacts.h" + +bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, std::set * ignoredArtifacts) +{ + assert(hero); + const auto art = hero->getArt(slot); + assert(art); + + if(hero->tempOwner != LOCPLINT->playerID) + return false; + + auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), true); + if(!assemblyPossibilities.empty()) + { + auto askThread = new boost::thread([this, hero, art, slot, assemblyPossibilities, ignoredArtifacts]() -> void + { + boost::mutex::scoped_lock askLock(askAssembleArtifactsMutex); + for(const auto combinedArt : assemblyPossibilities) + { + boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex); + if(ignoredArtifacts && vstd::contains(*ignoredArtifacts, combinedArt->getId())) + continue; + + bool assembleConfirmed = false; + MetaString message = MetaString::createFromTextID(art->artType->getDescriptionTextID()); + message.appendEOL(); + message.appendEOL(); + message.appendRawString(CGI->generaltexth->allTexts[732]); // You possess all of the components needed to assemble the + message.replaceName(ArtifactID(combinedArt->getId())); + LOCPLINT->showYesNoDialog(message.toString(), [&assembleConfirmed, hero, slot, combinedArt]() + { + assembleConfirmed = true; + LOCPLINT->cb.get()->assembleArtifacts(hero, slot, true, combinedArt->getId()); + }, nullptr, {std::make_shared(ComponentType::ARTIFACT, combinedArt->getId())}); + + LOCPLINT->waitWhileDialog(); + if(ignoredArtifacts) + ignoredArtifacts->emplace(combinedArt->getId()); + if(assembleConfirmed) + break; + } + }); + askThread->detach(); + return true; + } + return false; +} + +bool ArtifactsUIController::askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot) +{ + assert(hero); + const auto art = hero->getArt(slot); + assert(art); + + if(hero->tempOwner != LOCPLINT->playerID) + return false; + + if(art->isCombined()) + { + if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1)) + return false; + + MetaString message = MetaString::createFromTextID(art->artType->getDescriptionTextID()); + message.appendEOL(); + message.appendEOL(); + message.appendRawString(CGI->generaltexth->allTexts[733]); // Do you wish to disassemble this artifact? + LOCPLINT->showYesNoDialog(message.toString(), [hero, slot]() + { + LOCPLINT->cb->assembleArtifacts(hero, slot, false, ArtifactID()); + }, nullptr); + return true; + } + return false; +} + +void ArtifactsUIController::artifactRemoved() +{ + for(auto & artWin : GH.windows().findWindows()) + artWin->update(); + LOCPLINT->waitWhileDialog(); +} + +void ArtifactsUIController::artifactMoved() +{ + // If a bulk transfer has arrived, then redrawing only the last art movement. + if(numOfMovedArts != 0) + numOfMovedArts--; + + for(auto & artWin : GH.windows().findWindows()) + if(numOfMovedArts == 0) + { + artWin->update(); + artWin->redraw(); + } + LOCPLINT->waitWhileDialog(); +} + +void ArtifactsUIController::bulkArtMovementStart(size_t numOfArts) +{ + numOfMovedArts = numOfArts; + if(numOfArtsAskAssembleSession == 0) + { + // Do not start the next session until the previous one is finished + numOfArtsAskAssembleSession = numOfArts; // TODO this is wrong + ignoredArtifacts.clear(); + } +} + +void ArtifactsUIController::artifactAssembled() +{ + for(auto & artWin : GH.windows().findWindows()) + artWin->update(); +} + +void ArtifactsUIController::artifactDisassembled() +{ + for(auto & artWin : GH.windows().findWindows()) + artWin->update(); +} diff --git a/client/ArtifactsUIController.h b/client/ArtifactsUIController.h new file mode 100644 index 000000000..0378dc9ee --- /dev/null +++ b/client/ArtifactsUIController.h @@ -0,0 +1,38 @@ +/* + * ArtifactsUIController.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 "../lib/constants/EntityIdentifiers.h" + +VCMI_LIB_NAMESPACE_BEGIN + +class CGHeroInstance; + +VCMI_LIB_NAMESPACE_END + +class ArtifactsUIController +{ +public: + size_t numOfMovedArts; + size_t numOfArtsAskAssembleSession; + std::set ignoredArtifacts; + + boost::mutex askAssembleArtifactsMutex; + + bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, std::set * ignoredArtifacts = nullptr); + bool askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot); + + void artifactRemoved(); + void artifactMoved(); + void bulkArtMovementStart(size_t numOfArts); + void artifactAssembled(); + void artifactDisassembled(); +}; + \ No newline at end of file diff --git a/client/CMakeLists.txt b/client/CMakeLists.txt index 36fc2c8a5..65f156973 100644 --- a/client/CMakeLists.txt +++ b/client/CMakeLists.txt @@ -168,6 +168,7 @@ set(client_SRCS windows/settings/BattleOptionsTab.cpp windows/settings/AdventureOptionsTab.cpp + ArtifactsUIController.cpp CGameInfo.cpp CMT.cpp CPlayerInterface.cpp @@ -371,6 +372,7 @@ set(client_HEADERS windows/settings/BattleOptionsTab.h windows/settings/AdventureOptionsTab.h + ArtifactsUIController.h CGameInfo.h CMT.h CPlayerInterface.h diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index 3bad090da..ae0f33e9f 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -1251,35 +1251,6 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer GH.windows().pushWindow(cgw); } -/** - * Shows the dialog that appears when right-clicking an artifact that can be assembled - * into a combinational one on an artifact screen. Does not require the combination of - * artifacts to be legal. - */ -void CPlayerInterface::showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList onYes) -{ - std::string text = artifact->getDescriptionTranslated(); - text += "\n\n"; - std::vector> scs; - - if(assembledArtifact) - { - // You possess all of the components to... - text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact->getNameTranslated()); - - // Picture of assembled artifact at bottom. - auto sc = std::make_shared(ComponentType::ARTIFACT, assembledArtifact->getId()); - scs.push_back(sc); - } - else - { - // Do you wish to disassemble this artifact? - text += CGI->generaltexth->allTexts[733]; - } - - showYesNoDialog(text, onYes, nullptr, scs); -} - void CPlayerInterface::requestRealized( PackageApplied *pa ) { if(pa->packType == CTypeList::getInstance().getTypeID(nullptr)) @@ -1739,14 +1710,14 @@ void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al) { if(auto hero = cb->getHero(al.artHolder)) { - auto art = hero->getArt(al.slot); - if(art == nullptr) + if(hero->getArt(al.slot) == nullptr) { - logGlobal->error("artifact location %d points to nothing", - al.slot.num); + logGlobal->error("artifact location %d points to nothing", al.slot.num); return; } - ArtifactUtilsClient::askToAssemble(hero, al.slot); + askToAssemble(hero, al.slot, &ignoredArtifacts); + if(numOfArtsAskAssembleSession != 0) + numOfArtsAskAssembleSession--; } } @@ -1760,55 +1731,33 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(al.artHolder)); - - for(auto artWin : GH.windows().findWindows()) - artWin->artifactRemoved(al); - - waitWhileDialog(); + ArtifactsUIController::artifactRemoved(); } void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(dst.artHolder)); - - // If a bulk transfer has arrived, then redrawing only the last art movement. - if(numOfMovedArts != 0) - numOfMovedArts--; - - for(auto artWin : GH.windows().findWindows()) - { - artWin->artifactMoved(src, dst); - if(numOfMovedArts == 0) - { - artWin->update(); - artWin->redraw(); - } - } - waitWhileDialog(); + ArtifactsUIController::artifactMoved(); } void CPlayerInterface::bulkArtMovementStart(size_t numOfArts) { - numOfMovedArts = numOfArts; + ArtifactsUIController::bulkArtMovementStart(numOfArts); } void CPlayerInterface::artifactAssembled(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(al.artHolder)); - - for(auto artWin : GH.windows().findWindows()) - artWin->artifactAssembled(al); + ArtifactsUIController::artifactAssembled(); } void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(al.artHolder)); - - for(auto artWin : GH.windows().findWindows()) - artWin->artifactDisassembled(al); + ArtifactsUIController::artifactDisassembled(); } void CPlayerInterface::waitForAllDialogs() diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 25f671864..9ac6e32eb 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -12,6 +12,7 @@ #include "../lib/FunctionList.h" #include "../lib/CGameInterface.h" #include "gui/CIntObject.h" +#include "ArtifactsUIController.h" VCMI_LIB_NAMESPACE_BEGIN @@ -56,11 +57,9 @@ namespace boost } /// Central class for managing user interface logic -class CPlayerInterface : public CGameInterface, public IUpdateable +class CPlayerInterface : public CGameInterface, public IUpdateable, public ArtifactsUIController { bool ignoreEvents; - size_t numOfMovedArts; - int autosaveCount; std::list> dialogs; //queue of dialogs awaiting to be shown (not currently shown!) @@ -180,7 +179,6 @@ public: // public interface for use by client via LOCPLINT access void showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard; void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2); - void showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList onYes); void waitWhileDialog(); void waitForAllDialogs(); void openTownWindow(const CGTownInstance * town); //shows townscreen diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 8678d987c..3a7d4d1a0 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -307,7 +307,7 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack) const auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos); callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); - if(pack.askAssemble) + if(slotToMove.askAssemble) callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::askToAssembleArtifact, dstLoc); if(pack.interfaceOwner != dstOwner) callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); diff --git a/client/widgets/CArtPlace.cpp b/client/widgets/CArtPlace.cpp index 0e2b31139..520efd1be 100644 --- a/client/widgets/CArtPlace.cpp +++ b/client/widgets/CArtPlace.cpp @@ -245,59 +245,3 @@ void CArtPlace::addCombinedArtInfo(const std::mapgetArt(slot); - assert(art); - - if(hero->tempOwner != LOCPLINT->playerID) - return false; - - auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId()); - if(!assemblyPossibilities.empty()) - { - auto askThread = new boost::thread([hero, art, slot, assemblyPossibilities]() -> void - { - boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex); - for(const auto combinedArt : assemblyPossibilities) - { - LOCPLINT->waitWhileDialog(); - bool assembleConfirmed = false; - CFunctionList onYesHandlers([&assembleConfirmed]() -> void {assembleConfirmed = true; }); - onYesHandlers += std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, true, combinedArt->getId()); - - LOCPLINT->showArtifactAssemblyDialog(art->artType, combinedArt, onYesHandlers); - if(assembleConfirmed) - break; - } - }); - askThread->detach(); - return true; - } - return false; -} - -bool ArtifactUtilsClient::askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot) -{ - assert(hero); - const auto art = hero->getArt(slot); - assert(art); - - if(hero->tempOwner != LOCPLINT->playerID) - return false; - - if(art->isCombined()) - { - if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1)) - return false; - - LOCPLINT->showArtifactAssemblyDialog( - art->artType, - nullptr, - std::bind(&CCallback::assembleArtifacts, LOCPLINT->cb.get(), hero, slot, false, ArtifactID())); - return true; - } - return false; -} diff --git a/client/widgets/CArtPlace.h b/client/widgets/CArtPlace.h index 4d62eca97..95ff02b7e 100644 --- a/client/widgets/CArtPlace.h +++ b/client/widgets/CArtPlace.h @@ -59,9 +59,3 @@ public: void clickPressed(const Point & cursorPosition) override; void showPopupWindow(const Point & cursorPosition) override; }; - -namespace ArtifactUtilsClient -{ - bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot); - bool askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot); -} diff --git a/client/windows/CWindowWithArtifacts.cpp b/client/windows/CWindowWithArtifacts.cpp index 1f8006a71..2326e481b 100644 --- a/client/windows/CWindowWithArtifacts.cpp +++ b/client/windows/CWindowWithArtifacts.cpp @@ -117,9 +117,9 @@ void CWindowWithArtifacts::showArtifactAssembling(const CArtifactsOfHeroBase & a { if(artsInst.getArt(artPlace.slot)) { - if(ArtifactUtilsClient::askToDisassemble(artsInst.getHero(), artPlace.slot)) + if(LOCPLINT->askToDisassemble(artsInst.getHero(), artPlace.slot)) return; - if(ArtifactUtilsClient::askToAssemble(artsInst.getHero(), artPlace.slot)) + if(LOCPLINT->askToAssemble(artsInst.getHero(), artPlace.slot)) return; if(artPlace.text.size()) artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition); @@ -166,14 +166,13 @@ void CWindowWithArtifacts::enableKeyboardShortcuts() const artSet->enableKeyboardShortcuts(); } -void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc) -{ - update(); -} - -void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc) +void CWindowWithArtifacts::update() { for(const auto & artSet : artSets) + { + artSet->updateWornSlots(); + artSet->updateBackpackSlots(); + if(const auto pickedArtInst = getPickedArtifact()) { markPossibleSlots(); @@ -184,25 +183,6 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const artSet->unmarkSlots(); CCS->curh->dragAndDropCursor(nullptr); } -} - -void CWindowWithArtifacts::artifactDisassembled(const ArtifactLocation & artLoc) -{ - update(); -} - -void CWindowWithArtifacts::artifactAssembled(const ArtifactLocation & artLoc) -{ - markPossibleSlots(); - update(); -} - -void CWindowWithArtifacts::update() -{ - for(const auto & artSet : artSets) - { - artSet->updateWornSlots(); - artSet->updateBackpackSlots(); // Make sure the status bar is updated so it does not display old text if(auto artPlace = artSet->getArtPlace(GH.getCursorPosition())) diff --git a/client/windows/CWindowWithArtifacts.h b/client/windows/CWindowWithArtifacts.h index 2eb3810f7..c6af89aba 100644 --- a/client/windows/CWindowWithArtifacts.h +++ b/client/windows/CWindowWithArtifacts.h @@ -37,10 +37,6 @@ public: void deactivate() override; void enableKeyboardShortcuts() const; - virtual void artifactRemoved(const ArtifactLocation & artLoc); - virtual void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc); - virtual void artifactDisassembled(const ArtifactLocation & artLoc); - virtual void artifactAssembled(const ArtifactLocation & artLoc); virtual void update(); protected: diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index 0ca32387b..dd0bd67ba 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -196,7 +196,7 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target, } DLL_LINKAGE std::vector ArtifactUtils::assemblyPossibilities( - const CArtifactSet * artSet, const ArtifactID & aid) + const CArtifactSet * artSet, const ArtifactID & aid, const bool onlyEquiped) { std::vector arts; const auto * art = aid.toArtifact(); @@ -210,7 +210,7 @@ DLL_LINKAGE std::vector ArtifactUtils::assemblyPossibilities( for(const auto constituent : artifact->getConstituents()) //check if all constituents are available { - if(!artSet->hasArt(constituent->getId(), false, false, false)) + if(!artSet->hasArt(constituent->getId(), onlyEquiped, false, false)) { possible = false; break; diff --git a/lib/ArtifactUtils.h b/lib/ArtifactUtils.h index ef6d35de1..46eb878e6 100644 --- a/lib/ArtifactUtils.h +++ b/lib/ArtifactUtils.h @@ -39,7 +39,7 @@ namespace ArtifactUtils DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot); DLL_LINKAGE bool isSlotEquipment(const ArtifactPosition & slot); DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1); - DLL_LINKAGE std::vector assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid); + DLL_LINKAGE std::vector assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid, const bool onlyEquiped = false); DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const CArtifact * art); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid); diff --git a/lib/networkPacks/PacksForClient.h b/lib/networkPacks/PacksForClient.h index 70c3847f1..be9f94715 100644 --- a/lib/networkPacks/PacksForClient.h +++ b/lib/networkPacks/PacksForClient.h @@ -1031,17 +1031,20 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack { ArtifactPosition srcPos; ArtifactPosition dstPos; + bool askAssemble; LinkedSlots() = default; - LinkedSlots(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos) + LinkedSlots(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos, bool askAssemble = false) : srcPos(srcPos) , dstPos(dstPos) + , askAssemble(askAssemble) { } template void serialize(Handler & h) { h & srcPos; h & dstPos; + h & askAssemble; } }; @@ -1056,7 +1059,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack , srcArtHolder(ObjectInstanceID::NONE) , dstArtHolder(ObjectInstanceID::NONE) , swap(false) - , askAssemble(false) , srcCreature(std::nullopt) , dstCreature(std::nullopt) { @@ -1066,7 +1068,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack , srcArtHolder(srcArtHolder) , dstArtHolder(dstArtHolder) , swap(swap) - , askAssemble(false) , srcCreature(std::nullopt) , dstCreature(std::nullopt) { @@ -1077,7 +1078,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack std::vector artsPack0; std::vector artsPack1; bool swap; - bool askAssemble; void visitTyped(ICPackVisitor & visitor) override; @@ -1091,7 +1091,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack h & srcCreature; h & dstCreature; h & swap; - h & askAssemble; } }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 27984bbc4..2834deaaf 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2783,7 +2783,7 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot)); if(src.artHolder != dst.artHolder) - ma.askAssemble = true; + ma.artsPack0.back().askAssemble = true; sendAndApply(&ma); return true; } diff --git a/server/battles/BattleResultProcessor.cpp b/server/battles/BattleResultProcessor.cpp index b278bfbab..591e2885f 100644 --- a/server/battles/BattleResultProcessor.cpp +++ b/server/battles/BattleResultProcessor.cpp @@ -407,6 +407,8 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) if(dstSlot != ArtifactPosition::PRE_FIRST) { pack.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); + if(ArtifactUtils::isSlotEquipment(dstSlot)) + pack.artsPack0.back().askAssemble = true; arts.emplace_back(art); artFittingSet.putArtifact(dstSlot, const_cast(art)); } @@ -421,7 +423,6 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) if(finishingBattle->loserHero) { packHero.srcArtHolder = finishingBattle->loserHero->id; - packHero.askAssemble = true; for(const auto & artSlot : finishingBattle->loserHero->artifactsWorn) { if(ArtifactUtils::isArtRemovable(artSlot)) From b42c6dbf44a1e2cea02d8c89620beaac115781a7 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 23 Jun 2024 23:48:19 +0300 Subject: [PATCH 5/6] fixed regressions --- CCallback.cpp | 4 +- CCallback.h | 4 +- client/ArtifactsUIController.cpp | 55 +++++++++++++++------- client/ArtifactsUIController.h | 11 +++-- client/CPlayerInterface.cpp | 17 ++----- client/CPlayerInterface.h | 7 ++- client/NetPacksClient.cpp | 18 +++++-- client/widgets/markets/CAltarArtifacts.cpp | 2 +- client/windows/CWindowWithArtifacts.cpp | 1 + lib/IGameEventsReceiver.h | 2 +- lib/MetaString.h | 2 +- lib/networkPacks/PacksForClient.h | 4 -- server/CGameHandler.cpp | 1 - server/battles/BattleResultProcessor.cpp | 2 +- 14 files changed, 74 insertions(+), 56 deletions(-) diff --git a/CCallback.cpp b/CCallback.cpp index 7367c1edc..423223a73 100644 --- a/CCallback.cpp +++ b/CCallback.cpp @@ -173,9 +173,9 @@ bool CCallback::swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation * @param assembleTo If assemble is true, this represents the artifact ID of the combination * artifact to assemble to. Otherwise it's not used. */ -void CCallback::assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) +void CCallback::assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) { - AssembleArtifacts aa(hero->id, artifactSlot, assemble, assembleTo); + AssembleArtifacts aa(heroID, artifactSlot, assemble, assembleTo); sendRequest(&aa); } diff --git a/CCallback.h b/CCallback.h index cad5871d0..8c579ae61 100644 --- a/CCallback.h +++ b/CCallback.h @@ -93,7 +93,7 @@ public: virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0; virtual void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) = 0; virtual void manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume) = 0; - virtual void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0; + virtual void assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0; virtual void eraseArtifactByClient(const ArtifactLocation & al)=0; virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0; virtual void endTurn()=0; @@ -176,7 +176,7 @@ public: int bulkMergeStacks(ObjectInstanceID armyId, SlotID srcSlot) override; bool dismissHero(const CGHeroInstance * hero) override; bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override; - void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override; + void assembleArtifacts(const ObjectInstanceID & heroID, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) override; void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped = true, bool backpack = true) override; void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) override; void manageHeroCostume(ObjectInstanceID hero, size_t costumeIdx, bool saveCostume) override; diff --git a/client/ArtifactsUIController.cpp b/client/ArtifactsUIController.cpp index 859f350fe..9f84541cb 100644 --- a/client/ArtifactsUIController.cpp +++ b/client/ArtifactsUIController.cpp @@ -23,7 +23,22 @@ #include "widgets/CComponent.h" #include "windows/CWindowWithArtifacts.h" -bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, std::set * ignoredArtifacts) +bool ArtifactsUIController::askToAssemble(const ArtifactLocation & al, const bool onlyEquipped, std::set * ignoredArtifacts) +{ + if(auto hero = LOCPLINT->cb->getHero(al.artHolder)) + { + if(hero->getArt(al.slot) == nullptr) + { + logGlobal->error("artifact location %d points to nothing", al.slot.num); + return false; + } + return askToAssemble(hero, al.slot, onlyEquipped, ignoredArtifacts); + } + return false; +} + +bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, + const bool onlyEquipped, std::set * ignoredArtifacts) { assert(hero); const auto art = hero->getArt(slot); @@ -32,17 +47,23 @@ bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const Art if(hero->tempOwner != LOCPLINT->playerID) return false; - auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), true); + if(numOfArtsAskAssembleSession != 0) + numOfArtsAskAssembleSession--; + auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), onlyEquipped); if(!assemblyPossibilities.empty()) { auto askThread = new boost::thread([this, hero, art, slot, assemblyPossibilities, ignoredArtifacts]() -> void { - boost::mutex::scoped_lock askLock(askAssembleArtifactsMutex); + boost::mutex::scoped_lock askLock(askAssembleArtifactMutex); for(const auto combinedArt : assemblyPossibilities) { boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex); - if(ignoredArtifacts && vstd::contains(*ignoredArtifacts, combinedArt->getId())) - continue; + if(ignoredArtifacts) + { + if(vstd::contains(*ignoredArtifacts, combinedArt->getId())) + continue; + ignoredArtifacts->emplace(combinedArt->getId()); + } bool assembleConfirmed = false; MetaString message = MetaString::createFromTextID(art->artType->getDescriptionTextID()); @@ -53,12 +74,10 @@ bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const Art LOCPLINT->showYesNoDialog(message.toString(), [&assembleConfirmed, hero, slot, combinedArt]() { assembleConfirmed = true; - LOCPLINT->cb.get()->assembleArtifacts(hero, slot, true, combinedArt->getId()); + LOCPLINT->cb.get()->assembleArtifacts(hero->id, slot, true, combinedArt->getId()); }, nullptr, {std::make_shared(ComponentType::ARTIFACT, combinedArt->getId())}); LOCPLINT->waitWhileDialog(); - if(ignoredArtifacts) - ignoredArtifacts->emplace(combinedArt->getId()); if(assembleConfirmed) break; } @@ -89,7 +108,7 @@ bool ArtifactsUIController::askToDisassemble(const CGHeroInstance * hero, const message.appendRawString(CGI->generaltexth->allTexts[733]); // Do you wish to disassemble this artifact? LOCPLINT->showYesNoDialog(message.toString(), [hero, slot]() { - LOCPLINT->cb->assembleArtifacts(hero, slot, false, ArtifactID()); + LOCPLINT->cb->assembleArtifacts(hero->id, slot, false, ArtifactID()); }, nullptr); return true; } @@ -98,7 +117,7 @@ bool ArtifactsUIController::askToDisassemble(const CGHeroInstance * hero, const void ArtifactsUIController::artifactRemoved() { - for(auto & artWin : GH.windows().findWindows()) + for(const auto & artWin : GH.windows().findWindows()) artWin->update(); LOCPLINT->waitWhileDialog(); } @@ -109,34 +128,34 @@ void ArtifactsUIController::artifactMoved() if(numOfMovedArts != 0) numOfMovedArts--; - for(auto & artWin : GH.windows().findWindows()) - if(numOfMovedArts == 0) + if(numOfMovedArts == 0) + for(const auto & artWin : GH.windows().findWindows()) { artWin->update(); - artWin->redraw(); } LOCPLINT->waitWhileDialog(); } -void ArtifactsUIController::bulkArtMovementStart(size_t numOfArts) +void ArtifactsUIController::bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts) { - numOfMovedArts = numOfArts; + assert(totalNumOfArts >= possibleAssemblyNumOfArts); + numOfMovedArts = totalNumOfArts; if(numOfArtsAskAssembleSession == 0) { // Do not start the next session until the previous one is finished - numOfArtsAskAssembleSession = numOfArts; // TODO this is wrong + numOfArtsAskAssembleSession = possibleAssemblyNumOfArts; ignoredArtifacts.clear(); } } void ArtifactsUIController::artifactAssembled() { - for(auto & artWin : GH.windows().findWindows()) + for(const auto & artWin : GH.windows().findWindows()) artWin->update(); } void ArtifactsUIController::artifactDisassembled() { - for(auto & artWin : GH.windows().findWindows()) + for(const auto & artWin : GH.windows().findWindows()) artWin->update(); } diff --git a/client/ArtifactsUIController.h b/client/ArtifactsUIController.h index 0378dc9ee..5b425b59a 100644 --- a/client/ArtifactsUIController.h +++ b/client/ArtifactsUIController.h @@ -10,7 +10,8 @@ #pragma once #include "../lib/constants/EntityIdentifiers.h" - +#include "../lib/networkPacks/ArtifactLocation.h" + VCMI_LIB_NAMESPACE_BEGIN class CGHeroInstance; @@ -24,14 +25,16 @@ public: size_t numOfArtsAskAssembleSession; std::set ignoredArtifacts; - boost::mutex askAssembleArtifactsMutex; + boost::mutex askAssembleArtifactMutex; - bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, std::set * ignoredArtifacts = nullptr); + bool askToAssemble(const ArtifactLocation & al, const bool onlyEquipped = false, std::set * ignoredArtifacts = nullptr); + bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, const bool onlyEquipped = false, + std::set * ignoredArtifacts = nullptr); bool askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot); void artifactRemoved(); void artifactMoved(); - void bulkArtMovementStart(size_t numOfArts); + void bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts); void artifactAssembled(); void artifactDisassembled(); }; diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index ae0f33e9f..c5c3a47ea 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -66,7 +66,6 @@ #include "../CCallback.h" -#include "../lib/CArtHandler.h" #include "../lib/CConfigHandler.h" #include "../lib/CGeneralTextHandler.h" #include "../lib/CHeroHandler.h" @@ -1708,17 +1707,7 @@ void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj) void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al) { - if(auto hero = cb->getHero(al.artHolder)) - { - if(hero->getArt(al.slot) == nullptr) - { - logGlobal->error("artifact location %d points to nothing", al.slot.num); - return; - } - askToAssemble(hero, al.slot, &ignoredArtifacts); - if(numOfArtsAskAssembleSession != 0) - numOfArtsAskAssembleSession--; - } + ArtifactsUIController::askToAssemble(al, true, &ignoredArtifacts); } void CPlayerInterface::artifactPut(const ArtifactLocation &al) @@ -1741,9 +1730,9 @@ void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const Artifact ArtifactsUIController::artifactMoved(); } -void CPlayerInterface::bulkArtMovementStart(size_t numOfArts) +void CPlayerInterface::bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts) { - ArtifactsUIController::bulkArtMovementStart(numOfArts); + ArtifactsUIController::bulkArtMovementStart(totalNumOfArts, possibleAssemblyNumOfArts); } void CPlayerInterface::artifactAssembled(const ArtifactLocation &al) diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 9ac6e32eb..587b3e24b 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -9,17 +9,16 @@ */ #pragma once +#include "ArtifactsUIController.h" + #include "../lib/FunctionList.h" #include "../lib/CGameInterface.h" #include "gui/CIntObject.h" -#include "ArtifactsUIController.h" VCMI_LIB_NAMESPACE_BEGIN class Artifact; - struct TryMoveHero; -class CGHeroInstance; class CStack; class CCreature; struct CGPath; @@ -97,7 +96,7 @@ protected: // Call-ins from server, should not be called directly, but only via void artifactPut(const ArtifactLocation &al) override; void artifactRemoved(const ArtifactLocation &al) override; void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) override; - void bulkArtMovementStart(size_t numOfArts) override; + void bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts) override; void artifactAssembled(const ArtifactLocation &al) override; void askToAssembleArtifact(const ArtifactLocation & dst) override; void artifactDisassembled(const ArtifactLocation &al) override; diff --git a/client/NetPacksClient.cpp b/client/NetPacksClient.cpp index 3a7d4d1a0..3b1f31beb 100644 --- a/client/NetPacksClient.cpp +++ b/client/NetPacksClient.cpp @@ -316,13 +316,25 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack) } }; + size_t possibleAssemblyNumOfArts = 0; + const auto calcPossibleAssemblyNumOfArts = [&possibleAssemblyNumOfArts](const auto & slotToMove) + { + if(slotToMove.askAssemble) + possibleAssemblyNumOfArts++; + }; + std::for_each(pack.artsPack0.cbegin(), pack.artsPack0.cend(), calcPossibleAssemblyNumOfArts); + std::for_each(pack.artsPack1.cbegin(), pack.artsPack1.cend(), calcPossibleAssemblyNumOfArts); + + // Begin a session of bulk movement of arts. It is not necessary but useful for the client optimization. - callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size()); + callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::bulkArtMovementStart, + pack.artsPack0.size() + pack.artsPack1.size(), possibleAssemblyNumOfArts); if(pack.interfaceOwner != dstOwner) - callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size()); + callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::bulkArtMovementStart, + pack.artsPack0.size() + pack.artsPack1.size(), possibleAssemblyNumOfArts); applyMove(pack.artsPack0); - if(pack.swap) + if(!pack.artsPack1.empty()) applyMove(pack.artsPack1); } diff --git a/client/widgets/markets/CAltarArtifacts.cpp b/client/widgets/markets/CAltarArtifacts.cpp index bf4b57ad2..cf3f9285c 100644 --- a/client/widgets/markets/CAltarArtifacts.cpp +++ b/client/widgets/markets/CAltarArtifacts.cpp @@ -146,7 +146,7 @@ void CAltarArtifacts::updateAltarSlots() for(auto & tradeSlot : tradeSlotsMapNewArts) { assert(tradeSlot.first->id == -1); - assert(altarArtifacts->getSlotByInstance(tradeSlot.second) != ArtifactPosition::PRE_FIRST); + assert(altarArtifacts->getArtPos(tradeSlot.second) != ArtifactPosition::PRE_FIRST); tradeSlot.first->setID(tradeSlot.second->getTypeId().num); tradeSlot.first->subtitle->setText(std::to_string(calcExpCost(tradeSlot.second->getTypeId()))); } diff --git a/client/windows/CWindowWithArtifacts.cpp b/client/windows/CWindowWithArtifacts.cpp index 2326e481b..32b1075ac 100644 --- a/client/windows/CWindowWithArtifacts.cpp +++ b/client/windows/CWindowWithArtifacts.cpp @@ -188,6 +188,7 @@ void CWindowWithArtifacts::update() if(auto artPlace = artSet->getArtPlace(GH.getCursorPosition())) artPlace->hover(true); } + redraw(); } void CWindowWithArtifacts::markPossibleSlots() const diff --git a/lib/IGameEventsReceiver.h b/lib/IGameEventsReceiver.h index b428480b7..0e1c932f9 100644 --- a/lib/IGameEventsReceiver.h +++ b/lib/IGameEventsReceiver.h @@ -90,7 +90,7 @@ public: virtual void artifactAssembled(const ArtifactLocation &al){}; virtual void artifactDisassembled(const ArtifactLocation &al){}; virtual void artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst){}; - virtual void bulkArtMovementStart(size_t numOfArts) {}; + virtual void bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts) {}; virtual void askToAssembleArtifact(const ArtifactLocation & dst) {}; virtual void heroVisit(const CGHeroInstance *visitor, const CGObjectInstance *visitedObj, bool start){}; diff --git a/lib/MetaString.h b/lib/MetaString.h index d2b5b8a24..cd26bf2c3 100644 --- a/lib/MetaString.h +++ b/lib/MetaString.h @@ -49,7 +49,7 @@ private: REPLACE_TEXTID_STRING, REPLACE_NUMBER, REPLACE_POSITIVE_NUMBER, - APPEND_EOL + APPEND_EOL }; std::vector message; diff --git a/lib/networkPacks/PacksForClient.h b/lib/networkPacks/PacksForClient.h index be9f94715..d01ac40a7 100644 --- a/lib/networkPacks/PacksForClient.h +++ b/lib/networkPacks/PacksForClient.h @@ -1058,7 +1058,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack : interfaceOwner(PlayerColor::NEUTRAL) , srcArtHolder(ObjectInstanceID::NONE) , dstArtHolder(ObjectInstanceID::NONE) - , swap(false) , srcCreature(std::nullopt) , dstCreature(std::nullopt) { @@ -1067,7 +1066,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack : interfaceOwner(interfaceOwner) , srcArtHolder(srcArtHolder) , dstArtHolder(dstArtHolder) - , swap(swap) , srcCreature(std::nullopt) , dstCreature(std::nullopt) { @@ -1077,7 +1075,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack std::vector artsPack0; std::vector artsPack1; - bool swap; void visitTyped(ICPackVisitor & visitor) override; @@ -1090,7 +1087,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack h & dstArtHolder; h & srcCreature; h & dstCreature; - h & swap; } }; diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 2834deaaf..4f060ff98 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -2774,7 +2774,6 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati // Previous artifact must be swapped COMPLAIN_RET_FALSE_IF(!dstArtifact->canBePutAt(srcArtSet, src.slot, true), "Cannot swap artifacts!"); ma.artsPack1.push_back(BulkMoveArtifacts::LinkedSlots(dstSlot, src.slot)); - ma.swap = true; } auto hero = getHero(dst.artHolder); diff --git a/server/battles/BattleResultProcessor.cpp b/server/battles/BattleResultProcessor.cpp index 591e2885f..6daf68a47 100644 --- a/server/battles/BattleResultProcessor.cpp +++ b/server/battles/BattleResultProcessor.cpp @@ -460,7 +460,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle) iw.player = finishingBattle->winnerHero->tempOwner; iw.text.appendLocalString(EMetaText::GENERAL_TXT, 30); //You have captured enemy artifact - for(auto art : arts) //TODO; separate function to display loot for various objects? + for(const auto art : arts) //TODO; separate function to display loot for various objects? { if(art->isScroll()) iw.components.emplace_back(ComponentType::SPELL_SCROLL, art->getScrollSpellID()); From ff5ddd76b71800ca82823e0d5436c47cdbd2f2ae Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Tue, 16 Jul 2024 00:03:06 +0300 Subject: [PATCH 6/6] suggestions --- client/ArtifactsUIController.cpp | 19 ++++++++++++------- client/ArtifactsUIController.h | 7 ++++--- client/CPlayerInterface.cpp | 17 +++++++++-------- client/CPlayerInterface.h | 3 ++- client/windows/CWindowWithArtifacts.cpp | 4 ++-- 5 files changed, 29 insertions(+), 21 deletions(-) diff --git a/client/ArtifactsUIController.cpp b/client/ArtifactsUIController.cpp index 9f84541cb..38083b4f8 100644 --- a/client/ArtifactsUIController.cpp +++ b/client/ArtifactsUIController.cpp @@ -23,7 +23,12 @@ #include "widgets/CComponent.h" #include "windows/CWindowWithArtifacts.h" -bool ArtifactsUIController::askToAssemble(const ArtifactLocation & al, const bool onlyEquipped, std::set * ignoredArtifacts) +ArtifactsUIController::ArtifactsUIController() +{ + numOfMovedArts = 0; +} + +bool ArtifactsUIController::askToAssemble(const ArtifactLocation & al, const bool onlyEquipped, const bool checkIgnored) { if(auto hero = LOCPLINT->cb->getHero(al.artHolder)) { @@ -32,13 +37,13 @@ bool ArtifactsUIController::askToAssemble(const ArtifactLocation & al, const boo logGlobal->error("artifact location %d points to nothing", al.slot.num); return false; } - return askToAssemble(hero, al.slot, onlyEquipped, ignoredArtifacts); + return askToAssemble(hero, al.slot, onlyEquipped, checkIgnored); } return false; } bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, - const bool onlyEquipped, std::set * ignoredArtifacts) + const bool onlyEquipped, const bool checkIgnored) { assert(hero); const auto art = hero->getArt(slot); @@ -52,17 +57,17 @@ bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const Art auto assemblyPossibilities = ArtifactUtils::assemblyPossibilities(hero, art->getTypeId(), onlyEquipped); if(!assemblyPossibilities.empty()) { - auto askThread = new boost::thread([this, hero, art, slot, assemblyPossibilities, ignoredArtifacts]() -> void + auto askThread = new boost::thread([this, hero, art, slot, assemblyPossibilities, checkIgnored]() -> void { boost::mutex::scoped_lock askLock(askAssembleArtifactMutex); for(const auto combinedArt : assemblyPossibilities) { boost::mutex::scoped_lock interfaceLock(GH.interfaceMutex); - if(ignoredArtifacts) + if(checkIgnored) { - if(vstd::contains(*ignoredArtifacts, combinedArt->getId())) + if(vstd::contains(ignoredArtifacts, combinedArt->getId())) continue; - ignoredArtifacts->emplace(combinedArt->getId()); + ignoredArtifacts.emplace(combinedArt->getId()); } bool assembleConfirmed = false; diff --git a/client/ArtifactsUIController.h b/client/ArtifactsUIController.h index 5b425b59a..94f209399 100644 --- a/client/ArtifactsUIController.h +++ b/client/ArtifactsUIController.h @@ -20,16 +20,17 @@ VCMI_LIB_NAMESPACE_END class ArtifactsUIController { -public: size_t numOfMovedArts; size_t numOfArtsAskAssembleSession; std::set ignoredArtifacts; boost::mutex askAssembleArtifactMutex; - bool askToAssemble(const ArtifactLocation & al, const bool onlyEquipped = false, std::set * ignoredArtifacts = nullptr); +public: + ArtifactsUIController(); + bool askToAssemble(const ArtifactLocation & al, const bool onlyEquipped = false, const bool checkIgnored = false); bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, const bool onlyEquipped = false, - std::set * ignoredArtifacts = nullptr); + const bool checkIgnored = false); bool askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot); void artifactRemoved(); diff --git a/client/CPlayerInterface.cpp b/client/CPlayerInterface.cpp index c5c3a47ea..a4e60d4bd 100644 --- a/client/CPlayerInterface.cpp +++ b/client/CPlayerInterface.cpp @@ -131,7 +131,9 @@ struct HeroObjectRetriever CPlayerInterface::CPlayerInterface(PlayerColor Player): localState(std::make_unique(*this)), - movementController(std::make_unique()) + movementController(std::make_unique()), + artifactController(std::make_unique()) + { logGlobal->trace("\tHuman player interface for player %s being constructed", Player.toString()); GH.defActionsDef = 0; @@ -147,7 +149,6 @@ CPlayerInterface::CPlayerInterface(PlayerColor Player): isAutoFightOn = false; isAutoFightEndBattle = false; ignoreEvents = false; - numOfMovedArts = 0; } CPlayerInterface::~CPlayerInterface() @@ -1707,7 +1708,7 @@ void CPlayerInterface::showShipyardDialogOrProblemPopup(const IShipyard *obj) void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al) { - ArtifactsUIController::askToAssemble(al, true, &ignoredArtifacts); + artifactController->askToAssemble(al, true, true); } void CPlayerInterface::artifactPut(const ArtifactLocation &al) @@ -1720,33 +1721,33 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(al.artHolder)); - ArtifactsUIController::artifactRemoved(); + artifactController->artifactRemoved(); } void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(dst.artHolder)); - ArtifactsUIController::artifactMoved(); + artifactController->artifactMoved(); } void CPlayerInterface::bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts) { - ArtifactsUIController::bulkArtMovementStart(totalNumOfArts, possibleAssemblyNumOfArts); + artifactController->bulkArtMovementStart(totalNumOfArts, possibleAssemblyNumOfArts); } void CPlayerInterface::artifactAssembled(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(al.artHolder)); - ArtifactsUIController::artifactAssembled(); + artifactController->artifactAssembled(); } void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al) { EVENT_HANDLER_CALLED_BY_CLIENT; adventureInt->onHeroChanged(cb->getHero(al.artHolder)); - ArtifactsUIController::artifactDisassembled(); + artifactController->artifactDisassembled(); } void CPlayerInterface::waitForAllDialogs() diff --git a/client/CPlayerInterface.h b/client/CPlayerInterface.h index 587b3e24b..3fce1bd58 100644 --- a/client/CPlayerInterface.h +++ b/client/CPlayerInterface.h @@ -56,7 +56,7 @@ namespace boost } /// Central class for managing user interface logic -class CPlayerInterface : public CGameInterface, public IUpdateable, public ArtifactsUIController +class CPlayerInterface : public CGameInterface, public IUpdateable { bool ignoreEvents; int autosaveCount; @@ -65,6 +65,7 @@ class CPlayerInterface : public CGameInterface, public IUpdateable, public Artif std::unique_ptr movementController; public: // TODO: make private + std::unique_ptr artifactController; std::shared_ptr env; std::unique_ptr localState; diff --git a/client/windows/CWindowWithArtifacts.cpp b/client/windows/CWindowWithArtifacts.cpp index 32b1075ac..86ca47e11 100644 --- a/client/windows/CWindowWithArtifacts.cpp +++ b/client/windows/CWindowWithArtifacts.cpp @@ -117,9 +117,9 @@ void CWindowWithArtifacts::showArtifactAssembling(const CArtifactsOfHeroBase & a { if(artsInst.getArt(artPlace.slot)) { - if(LOCPLINT->askToDisassemble(artsInst.getHero(), artPlace.slot)) + if(LOCPLINT->artifactController->askToDisassemble(artsInst.getHero(), artPlace.slot)) return; - if(LOCPLINT->askToAssemble(artsInst.getHero(), artPlace.slot)) + if(LOCPLINT->artifactController->askToAssemble(artsInst.getHero(), artPlace.slot)) return; if(artPlace.text.size()) artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition);