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(); } }