1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-28 08:48:48 +02:00

ArtifactsUIController class

This commit is contained in:
SoundSSGood 2024-06-22 19:29:39 +03:00
parent f87762bc96
commit ef1fbffad4
15 changed files with 212 additions and 169 deletions

View File

@ -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<ArtifactID> * 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<CComponent>(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<CWindowWithArtifacts>())
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<CWindowWithArtifacts>())
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<CWindowWithArtifacts>())
artWin->update();
}
void ArtifactsUIController::artifactDisassembled()
{
for(auto & artWin : GH.windows().findWindows<CWindowWithArtifacts>())
artWin->update();
}

View File

@ -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<ArtifactID> ignoredArtifacts;
boost::mutex askAssembleArtifactsMutex;
bool askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot, std::set<ArtifactID> * ignoredArtifacts = nullptr);
bool askToDisassemble(const CGHeroInstance * hero, const ArtifactPosition & slot);
void artifactRemoved();
void artifactMoved();
void bulkArtMovementStart(size_t numOfArts);
void artifactAssembled();
void artifactDisassembled();
};

View File

@ -168,6 +168,7 @@ set(client_SRCS
windows/settings/BattleOptionsTab.cpp windows/settings/BattleOptionsTab.cpp
windows/settings/AdventureOptionsTab.cpp windows/settings/AdventureOptionsTab.cpp
ArtifactsUIController.cpp
CGameInfo.cpp CGameInfo.cpp
CMT.cpp CMT.cpp
CPlayerInterface.cpp CPlayerInterface.cpp
@ -371,6 +372,7 @@ set(client_HEADERS
windows/settings/BattleOptionsTab.h windows/settings/BattleOptionsTab.h
windows/settings/AdventureOptionsTab.h windows/settings/AdventureOptionsTab.h
ArtifactsUIController.h
CGameInfo.h CGameInfo.h
CMT.h CMT.h
CPlayerInterface.h CPlayerInterface.h

View File

@ -1251,35 +1251,6 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
GH.windows().pushWindow(cgw); 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<void()> onYes)
{
std::string text = artifact->getDescriptionTranslated();
text += "\n\n";
std::vector<std::shared_ptr<CComponent>> 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<CComponent>(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 ) void CPlayerInterface::requestRealized( PackageApplied *pa )
{ {
if(pa->packType == CTypeList::getInstance().getTypeID<MoveHero>(nullptr)) if(pa->packType == CTypeList::getInstance().getTypeID<MoveHero>(nullptr))
@ -1739,14 +1710,14 @@ void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
{ {
if(auto hero = cb->getHero(al.artHolder)) if(auto hero = cb->getHero(al.artHolder))
{ {
auto art = hero->getArt(al.slot); if(hero->getArt(al.slot) == nullptr)
if(art == nullptr)
{ {
logGlobal->error("artifact location %d points to nothing", logGlobal->error("artifact location %d points to nothing", al.slot.num);
al.slot.num);
return; 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; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->onHeroChanged(cb->getHero(al.artHolder)); adventureInt->onHeroChanged(cb->getHero(al.artHolder));
ArtifactsUIController::artifactRemoved();
for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
artWin->artifactRemoved(al);
waitWhileDialog();
} }
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst) void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->onHeroChanged(cb->getHero(dst.artHolder)); adventureInt->onHeroChanged(cb->getHero(dst.artHolder));
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<CWindowWithArtifacts>())
{
artWin->artifactMoved(src, dst);
if(numOfMovedArts == 0)
{
artWin->update();
artWin->redraw();
}
}
waitWhileDialog();
} }
void CPlayerInterface::bulkArtMovementStart(size_t numOfArts) void CPlayerInterface::bulkArtMovementStart(size_t numOfArts)
{ {
numOfMovedArts = numOfArts; ArtifactsUIController::bulkArtMovementStart(numOfArts);
} }
void CPlayerInterface::artifactAssembled(const ArtifactLocation &al) void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->onHeroChanged(cb->getHero(al.artHolder)); adventureInt->onHeroChanged(cb->getHero(al.artHolder));
ArtifactsUIController::artifactAssembled();
for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
artWin->artifactAssembled(al);
} }
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al) void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
{ {
EVENT_HANDLER_CALLED_BY_CLIENT; EVENT_HANDLER_CALLED_BY_CLIENT;
adventureInt->onHeroChanged(cb->getHero(al.artHolder)); adventureInt->onHeroChanged(cb->getHero(al.artHolder));
ArtifactsUIController::artifactDisassembled();
for(auto artWin : GH.windows().findWindows<CWindowWithArtifacts>())
artWin->artifactDisassembled(al);
} }
void CPlayerInterface::waitForAllDialogs() void CPlayerInterface::waitForAllDialogs()

View File

@ -12,6 +12,7 @@
#include "../lib/FunctionList.h" #include "../lib/FunctionList.h"
#include "../lib/CGameInterface.h" #include "../lib/CGameInterface.h"
#include "gui/CIntObject.h" #include "gui/CIntObject.h"
#include "ArtifactsUIController.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -56,11 +57,9 @@ namespace boost
} }
/// Central class for managing user interface logic /// Central class for managing user interface logic
class CPlayerInterface : public CGameInterface, public IUpdateable class CPlayerInterface : public CGameInterface, public IUpdateable, public ArtifactsUIController
{ {
bool ignoreEvents; bool ignoreEvents;
size_t numOfMovedArts;
int autosaveCount; int autosaveCount;
std::list<std::shared_ptr<CInfoWindow>> dialogs; //queue of dialogs awaiting to be shown (not currently shown!) std::list<std::shared_ptr<CInfoWindow>> 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 showShipyardDialog(const IShipyard *obj) override; //obj may be town or shipyard;
void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2); void showHeroExchange(ObjectInstanceID hero1, ObjectInstanceID hero2);
void showArtifactAssemblyDialog(const Artifact * artifact, const Artifact * assembledArtifact, CFunctionList<void()> onYes);
void waitWhileDialog(); void waitWhileDialog();
void waitForAllDialogs(); void waitForAllDialogs();
void openTownWindow(const CGTownInstance * town); //shows townscreen void openTownWindow(const CGTownInstance * town); //shows townscreen

View File

@ -307,7 +307,7 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
const auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos); const auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos);
callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);
if(pack.askAssemble) if(slotToMove.askAssemble)
callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::askToAssembleArtifact, dstLoc); callInterfaceIfPresent(cl, pack.interfaceOwner, &IGameEventsReceiver::askToAssembleArtifact, dstLoc);
if(pack.interfaceOwner != dstOwner) if(pack.interfaceOwner != dstOwner)
callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc); callInterfaceIfPresent(cl, dstOwner, &IGameEventsReceiver::artifactMoved, srcLoc, dstLoc);

View File

@ -245,59 +245,3 @@ void CArtPlace::addCombinedArtInfo(const std::map<const ArtifactID, std::vector<
text += info.toString(); text += info.toString();
} }
} }
bool ArtifactUtilsClient::askToAssemble(const CGHeroInstance * hero, const ArtifactPosition & slot)
{
assert(hero);
const auto art = hero->getArt(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<void()> 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;
}

View File

@ -59,9 +59,3 @@ public:
void clickPressed(const Point & cursorPosition) override; void clickPressed(const Point & cursorPosition) override;
void showPopupWindow(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);
}

View File

@ -117,9 +117,9 @@ void CWindowWithArtifacts::showArtifactAssembling(const CArtifactsOfHeroBase & a
{ {
if(artsInst.getArt(artPlace.slot)) if(artsInst.getArt(artPlace.slot))
{ {
if(ArtifactUtilsClient::askToDisassemble(artsInst.getHero(), artPlace.slot)) if(LOCPLINT->askToDisassemble(artsInst.getHero(), artPlace.slot))
return; return;
if(ArtifactUtilsClient::askToAssemble(artsInst.getHero(), artPlace.slot)) if(LOCPLINT->askToAssemble(artsInst.getHero(), artPlace.slot))
return; return;
if(artPlace.text.size()) if(artPlace.text.size())
artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition); artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition);
@ -166,14 +166,13 @@ void CWindowWithArtifacts::enableKeyboardShortcuts() const
artSet->enableKeyboardShortcuts(); artSet->enableKeyboardShortcuts();
} }
void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc) void CWindowWithArtifacts::update()
{
update();
}
void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc)
{ {
for(const auto & artSet : artSets) for(const auto & artSet : artSets)
{
artSet->updateWornSlots();
artSet->updateBackpackSlots();
if(const auto pickedArtInst = getPickedArtifact()) if(const auto pickedArtInst = getPickedArtifact())
{ {
markPossibleSlots(); markPossibleSlots();
@ -184,25 +183,6 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
artSet->unmarkSlots(); artSet->unmarkSlots();
CCS->curh->dragAndDropCursor(nullptr); 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 // Make sure the status bar is updated so it does not display old text
if(auto artPlace = artSet->getArtPlace(GH.getCursorPosition())) if(auto artPlace = artSet->getArtPlace(GH.getCursorPosition()))

View File

@ -37,10 +37,6 @@ public:
void deactivate() override; void deactivate() override;
void enableKeyboardShortcuts() const; 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(); virtual void update();
protected: protected:

View File

@ -196,7 +196,7 @@ DLL_LINKAGE bool ArtifactUtils::isBackpackFreeSlots(const CArtifactSet * target,
} }
DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities( DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
const CArtifactSet * artSet, const ArtifactID & aid) const CArtifactSet * artSet, const ArtifactID & aid, const bool onlyEquiped)
{ {
std::vector<const CArtifact*> arts; std::vector<const CArtifact*> arts;
const auto * art = aid.toArtifact(); const auto * art = aid.toArtifact();
@ -210,7 +210,7 @@ DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
for(const auto constituent : artifact->getConstituents()) //check if all constituents are available 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; possible = false;
break; break;

View File

@ -39,7 +39,7 @@ namespace ArtifactUtils
DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot); DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot);
DLL_LINKAGE bool isSlotEquipment(const ArtifactPosition & slot); DLL_LINKAGE bool isSlotEquipment(const ArtifactPosition & slot);
DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1); DLL_LINKAGE bool isBackpackFreeSlots(const CArtifactSet * target, const size_t reqSlots = 1);
DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid); DLL_LINKAGE std::vector<const CArtifact*> assemblyPossibilities(const CArtifactSet * artSet, const ArtifactID & aid, const bool onlyEquiped = false);
DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid); DLL_LINKAGE CArtifactInstance * createScroll(const SpellID & sid);
DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const CArtifact * art); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const CArtifact * art);
DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid);

View File

@ -1031,17 +1031,20 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
{ {
ArtifactPosition srcPos; ArtifactPosition srcPos;
ArtifactPosition dstPos; ArtifactPosition dstPos;
bool askAssemble;
LinkedSlots() = default; LinkedSlots() = default;
LinkedSlots(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos) LinkedSlots(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos, bool askAssemble = false)
: srcPos(srcPos) : srcPos(srcPos)
, dstPos(dstPos) , dstPos(dstPos)
, askAssemble(askAssemble)
{ {
} }
template <typename Handler> void serialize(Handler & h) template <typename Handler> void serialize(Handler & h)
{ {
h & srcPos; h & srcPos;
h & dstPos; h & dstPos;
h & askAssemble;
} }
}; };
@ -1056,7 +1059,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
, srcArtHolder(ObjectInstanceID::NONE) , srcArtHolder(ObjectInstanceID::NONE)
, dstArtHolder(ObjectInstanceID::NONE) , dstArtHolder(ObjectInstanceID::NONE)
, swap(false) , swap(false)
, askAssemble(false)
, srcCreature(std::nullopt) , srcCreature(std::nullopt)
, dstCreature(std::nullopt) , dstCreature(std::nullopt)
{ {
@ -1066,7 +1068,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
, srcArtHolder(srcArtHolder) , srcArtHolder(srcArtHolder)
, dstArtHolder(dstArtHolder) , dstArtHolder(dstArtHolder)
, swap(swap) , swap(swap)
, askAssemble(false)
, srcCreature(std::nullopt) , srcCreature(std::nullopt)
, dstCreature(std::nullopt) , dstCreature(std::nullopt)
{ {
@ -1077,7 +1078,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
std::vector<LinkedSlots> artsPack0; std::vector<LinkedSlots> artsPack0;
std::vector<LinkedSlots> artsPack1; std::vector<LinkedSlots> artsPack1;
bool swap; bool swap;
bool askAssemble;
void visitTyped(ICPackVisitor & visitor) override; void visitTyped(ICPackVisitor & visitor) override;
@ -1091,7 +1091,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
h & srcCreature; h & srcCreature;
h & dstCreature; h & dstCreature;
h & swap; h & swap;
h & askAssemble;
} }
}; };

View File

@ -2783,7 +2783,7 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati
ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot)); ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot));
if(src.artHolder != dst.artHolder) if(src.artHolder != dst.artHolder)
ma.askAssemble = true; ma.artsPack0.back().askAssemble = true;
sendAndApply(&ma); sendAndApply(&ma);
return true; return true;
} }

View File

@ -407,6 +407,8 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
if(dstSlot != ArtifactPosition::PRE_FIRST) if(dstSlot != ArtifactPosition::PRE_FIRST)
{ {
pack.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); pack.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
if(ArtifactUtils::isSlotEquipment(dstSlot))
pack.artsPack0.back().askAssemble = true;
arts.emplace_back(art); arts.emplace_back(art);
artFittingSet.putArtifact(dstSlot, const_cast<CArtifactInstance*>(art)); artFittingSet.putArtifact(dstSlot, const_cast<CArtifactInstance*>(art));
} }
@ -421,7 +423,6 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
if(finishingBattle->loserHero) if(finishingBattle->loserHero)
{ {
packHero.srcArtHolder = finishingBattle->loserHero->id; packHero.srcArtHolder = finishingBattle->loserHero->id;
packHero.askAssemble = true;
for(const auto & artSlot : finishingBattle->loserHero->artifactsWorn) for(const auto & artSlot : finishingBattle->loserHero->artifactsWorn)
{ {
if(ArtifactUtils::isArtRemovable(artSlot)) if(ArtifactUtils::isArtRemovable(artSlot))