1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-08-10 22:31:40 +02:00

ArtInfoWindow on client. Client side

This commit is contained in:
SoundSSGood
2025-04-05 22:55:57 +02:00
parent 7b89521179
commit f0a9c95075
11 changed files with 83 additions and 48 deletions

View File

@@ -60,10 +60,9 @@ bool ArtifactsUIController::askToAssemble(const CGHeroInstance * hero, const Art
{
auto askThread = new std::thread([this, hero, art, slot, assemblyPossibilities, checkIgnored]() -> void
{
std::scoped_lock askLock(askAssembleArtifactMutex);
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
for(const auto combinedArt : assemblyPossibilities)
{
std::scoped_lock interfaceLock(ENGINE->interfaceMutex);
if(checkIgnored)
{
if(vstd::contains(ignoredArtifacts, combinedArt->getId()))
@@ -168,3 +167,19 @@ void ArtifactsUIController::artifactDisassembled()
for(const auto & artWin : ENGINE->windows().findWindows<CWindowWithArtifacts>())
artWin->update();
}
std::vector<Component> ArtifactsUIController::getMovedComponents(const CArtifactSet & artSet, const std::vector<MoveArtifactInfo> & movedPack) const
{
std::vector<Component> components;
for(const auto & artMoveInfo : movedPack)
{
const auto art = artSet.getArt(artMoveInfo.dstPos);
assert(art);
if(art->isScroll())
components.emplace_back(ComponentType::SPELL_SCROLL, art->getScrollSpellID());
else
components.emplace_back(ComponentType::ARTIFACT, art->getTypeId());
}
return components;
}

View File

@@ -14,7 +14,9 @@
VCMI_LIB_NAMESPACE_BEGIN
class CArtifactSet;
class CGHeroInstance;
struct Component;
VCMI_LIB_NAMESPACE_END
@@ -24,8 +26,6 @@ class ArtifactsUIController
size_t numOfArtsAskAssembleSession;
std::set<ArtifactID> ignoredArtifacts;
std::mutex askAssembleArtifactMutex;
public:
ArtifactsUIController();
bool askToAssemble(const ArtifactLocation & al, const bool onlyEquipped = false, const bool checkIgnored = false);
@@ -38,5 +38,5 @@ public:
void bulkArtMovementStart(size_t totalNumOfArts, size_t possibleAssemblyNumOfArts);
void artifactAssembled();
void artifactDisassembled();
std::vector<Component> getMovedComponents(const CArtifactSet & artSet, const std::vector<MoveArtifactInfo> & movedPack) const;
};

View File

@@ -1072,6 +1072,7 @@ void CPlayerInterface::showInfoDialogAndWait(std::vector<Component> & components
void CPlayerInterface::showYesNoDialog(const std::string &text, CFunctionList<void()> onYes, CFunctionList<void()> onNo, const std::vector<std::shared_ptr<CComponent>> & components)
{
waitWhileDialog();
movementController->requestMovementAbort();
GAME->interface()->showingDialog->setBusy();
CInfoWindow::showYesNoDialog(text, components, onYes, onNo, playerID);

View File

@@ -291,7 +291,7 @@ void ApplyClientNetPackVisitor::visitEraseArtifact(BulkEraseArtifacts & pack)
void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
{
const auto dstOwner = cl.getOwner(pack.dstArtHolder);
const auto applyMove = [this, &pack, dstOwner](std::vector<BulkMoveArtifacts::LinkedSlots> & artsPack)
const auto applyMove = [this, &pack, dstOwner](const std::vector<MoveArtifactInfo> & artsPack)
{
for(const auto & slotToMove : artsPack)
{
@@ -851,6 +851,22 @@ void ApplyClientNetPackVisitor::visitStacksInjured(StacksInjured & pack)
void ApplyClientNetPackVisitor::visitBattleResultsApplied(BattleResultsApplied & pack)
{
InfoWindow win;
win.player = pack.victor;
win.text.appendLocalString(EMetaText::GENERAL_TXT, 30);
const auto artSet = GAME->interface()->cb->getArtSet(ArtifactLocation(pack.artifacts.front().dstArtHolder));
assert(artSet);
for(const auto & artPack : pack.artifacts)
{
auto packComponents = GAME->interface()->artifactController->getMovedComponents(*artSet, artPack.artsPack0);
win.components.insert(win.components.end(), std::make_move_iterator(packComponents.begin()), std::make_move_iterator(packComponents.end()));
}
if(!win.components.empty())
visitInfoWindow(win);
for(auto & artPack : pack.artifacts)
visitBulkMoveArtifacts(artPack);
callInterfaceIfPresent(cl, pack.victor, &IGameEventsReceiver::battleResultsApplied);
callInterfaceIfPresent(cl, pack.loser, &IGameEventsReceiver::battleResultsApplied);
callInterfaceIfPresent(cl, PlayerColor::SPECTATOR, &IGameEventsReceiver::battleResultsApplied);

View File

@@ -10,6 +10,7 @@
#pragma once
#include "../constants/EntityIdentifiers.h"
#include <optional>
VCMI_LIB_NAMESPACE_BEGIN
@@ -52,4 +53,31 @@ struct ArtifactLocation
}
};
struct MoveArtifactInfo
{
ArtifactPosition srcPos;
ArtifactPosition dstPos;
bool askAssemble;
MoveArtifactInfo()
: srcPos(ArtifactPosition::PRE_FIRST)
, dstPos(ArtifactPosition::PRE_FIRST)
, askAssemble(false)
{
}
MoveArtifactInfo(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos, bool askAssemble = false)
: srcPos(srcPos)
, dstPos(dstPos)
, askAssemble(askAssemble)
{
}
template <typename Handler> void serialize(Handler & h)
{
h & srcPos;
h & dstPos;
h & askAssemble;
}
};
VCMI_LIB_NAMESPACE_END

View File

@@ -1766,7 +1766,7 @@ void BulkEraseArtifacts::applyGs(CGameState *gs)
void BulkMoveArtifacts::applyGs(CGameState *gs)
{
const auto bulkArtsRemove = [gs](std::vector<LinkedSlots> & artsPack, CArtifactSet & artSet)
const auto bulkArtsRemove = [gs](std::vector<MoveArtifactInfo> & artsPack, CArtifactSet & artSet)
{
std::vector<ArtifactPosition> packToRemove;
for(const auto & slotsPair : artsPack)
@@ -1780,7 +1780,7 @@ void BulkMoveArtifacts::applyGs(CGameState *gs)
gs->getMap().removeArtifactInstance(artSet, slot);
};
const auto bulkArtsPut = [gs](std::vector<LinkedSlots> & artsPack, CArtifactSet & initArtSet, CArtifactSet & dstArtSet)
const auto bulkArtsPut = [gs](std::vector<MoveArtifactInfo> & artsPack, CArtifactSet & initArtSet, CArtifactSet & dstArtSet)
{
for(const auto & slotsPair : artsPack)
{

View File

@@ -1049,27 +1049,6 @@ struct DLL_LINKAGE BulkEraseArtifacts : CArtifactOperationPack
struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
{
struct LinkedSlots
{
ArtifactPosition srcPos;
ArtifactPosition dstPos;
bool askAssemble;
LinkedSlots() = default;
LinkedSlots(const ArtifactPosition & srcPos, const ArtifactPosition & dstPos, bool askAssemble = false)
: srcPos(srcPos)
, dstPos(dstPos)
, askAssemble(askAssemble)
{
}
template <typename Handler> void serialize(Handler & h)
{
h & srcPos;
h & dstPos;
h & askAssemble;
}
};
PlayerColor interfaceOwner;
ObjectInstanceID srcArtHolder;
ObjectInstanceID dstArtHolder;
@@ -1095,8 +1074,8 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
void applyGs(CGameState * gs) override;
std::vector<LinkedSlots> artsPack0;
std::vector<LinkedSlots> artsPack1;
std::vector<MoveArtifactInfo> artsPack0;
std::vector<MoveArtifactInfo> artsPack1;
void visitTyped(ICPackVisitor & visitor) override;

View File

@@ -2643,14 +2643,14 @@ 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.artsPack1.emplace_back(dstSlot, src.slot);
}
auto hero = getHero(dst.artHolder);
if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->getTypeId(), dstSlot))
giveHeroNewArtifact(hero, ArtifactID::SPELLBOOK, ArtifactPosition::SPELLBOOK);
ma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(src.slot, dstSlot));
ma.artsPack0.emplace_back(src.slot, dstSlot);
if(src.artHolder != dst.artHolder && !isDstSlotBackpack)
ma.artsPack0.back().askAssemble = true;
sendAndApply(ma);
@@ -2676,14 +2676,14 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI
CArtifactFittingSet artFittingSet(pdstSet->bearerType());
auto moveArtifact = [this, &artFittingSet, dstId](const CArtifactInstance * artifact,
ArtifactPosition srcSlot, std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
ArtifactPosition srcSlot, std::vector<MoveArtifactInfo> & slots) -> void
{
assert(artifact);
auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, artifact->getTypeId());
if(dstSlot != ArtifactPosition::PRE_FIRST)
{
artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact));
slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
slots.emplace_back(srcSlot, dstSlot);
// TODO Shouldn't be here. Possibly in callback after equipping the artifact
if(auto dstHero = getHero(dstId))
@@ -2696,7 +2696,7 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI
if(swap)
{
auto moveArtsWorn = [moveArtifact](const CArtifactSet * srcArtSet, std::vector<BulkMoveArtifacts::LinkedSlots> & slots)
auto moveArtsWorn = [moveArtifact](const CArtifactSet * srcArtSet, std::vector<MoveArtifactInfo> & slots)
{
for(auto & artifact : srcArtSet->artifactsWorn)
{
@@ -2705,12 +2705,12 @@ bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceI
}
};
auto moveArtsInBackpack = [](const CArtifactSet * artSet,
std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
std::vector<MoveArtifactInfo> & slots) -> void
{
for(auto & slotInfo : artSet->artifactsInBackpack)
{
auto slot = artSet->getArtPos(slotInfo.artifact);
slots.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot));
slots.emplace_back(slot, slot);
}
};
if(equipped)
@@ -2766,7 +2766,7 @@ bool CGameHandler::manageBackpackArtifacts(const PlayerColor & player, const Obj
BulkMoveArtifacts bma(player, heroID, heroID, false);
const auto makeSortBackpackRequest = [artSet, &bma](const std::function<int32_t(const ArtSlotInfo&)> & getSortId)
{
std::map<int32_t, std::vector<BulkMoveArtifacts::LinkedSlots>> packsSorted;
std::map<int32_t, std::vector<MoveArtifactInfo>> packsSorted;
ArtifactPosition backpackSlot = ArtifactPosition::BACKPACK_START;
for(const auto & backpackSlotInfo : artSet->artifactsInBackpack)
packsSorted.try_emplace(getSortId(backpackSlotInfo)).first->second.emplace_back(backpackSlot++, ArtifactPosition::PRE_FIRST);
@@ -2888,11 +2888,7 @@ bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const Obje
{
if(const auto slot = artFittingSet.getArtPos(artPos.second, false, false); slot != ArtifactPosition::PRE_FIRST)
{
bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots
{
artSet->getArtPos(artFittingSet.getArt(slot)),
artPos.first
});
bma.artsPack0.emplace_back(artSet->getArtPos(artFittingSet.getArt(slot)), artPos.first);
artFittingSet.removeArtifact(slot);
if(ArtifactUtils::isSlotBackpack(slot))
estimateBackpackSize--;
@@ -2903,7 +2899,7 @@ bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const Obje
for(const auto & slot : ArtifactUtils::commonWornSlots())
if(artFittingSet.getArt(slot))
{
bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots{slot, ArtifactPosition::BACKPACK_START});
bma.artsPack0.emplace_back(slot, ArtifactPosition::BACKPACK_START);
estimateBackpackSize++;
}

View File

@@ -392,7 +392,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
const auto dstSlot = ArtifactUtils::getArtAnyPosition(&artFittingSet, art->getTypeId());
if(dstSlot != ArtifactPosition::PRE_FIRST)
{
pack.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));
pack.artsPack0.emplace_back(MoveArtifactInfo(srcSlot, dstSlot));
if(ArtifactUtils::isSlotEquipment(dstSlot))
pack.artsPack0.back().askAssemble = true;
artFittingSet.putArtifact(dstSlot, const_cast<CArtifactInstance*>(art));

View File

@@ -47,7 +47,7 @@ struct FinishingBattleHelper
inline bool isDraw() const {return winnerSide == BattleSide::NONE;}
ObjectInstanceID winnerId, loserId;
ObjectInstanceID winnerId = ObjectInstanceID::NONE, loserId = ObjectInstanceID::NONE;
PlayerColor victor, loser;
BattleSide winnerSide;
std::vector<BulkMoveArtifacts> artifacts;

View File

@@ -68,7 +68,7 @@ public:
void tryJoiningArmy(const CArmedInstance *src, const CArmedInstance *dst, bool removeObjWhenFinished, bool allowMerging) override {} //merges army from src do dst or opens a garrison window
bool moveStack(const StackLocation &src, const StackLocation &dst, TQuantity count) override {return false;}
void removeAfterVisit(const CGObjectInstance *object) override {} //object will be destroyed when interaction is over. Do not call when interaction is not ongoing!
void removeAfterVisit(const ObjectInstanceID & id) override {} //object will be destroyed when interaction is over. Do not call when interaction is not ongoing!
bool giveHeroNewArtifact(const CGHeroInstance * h, const ArtifactID & artId, const ArtifactPosition & pos) override {return false;}
bool giveHeroNewScroll(const CGHeroInstance * h, const SpellID & spellId, const ArtifactPosition & pos) override {return false;}