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

Merge pull request #2874 from SoundSSGood/exchange-window-update

Exchange window update
This commit is contained in:
Ivan Savenko 2023-09-27 15:50:52 +03:00 committed by GitHub
commit 97097c20ad
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
35 changed files with 350 additions and 367 deletions

View File

@ -172,9 +172,9 @@ void CCallback::assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition
sendRequest(&aa);
}
void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack)
{
BulkExchangeArtifacts bma(srcHero, dstHero, swap);
BulkExchangeArtifacts bma(srcHero, dstHero, swap, equipped, backpack);
sendRequest(&bma);
}

View File

@ -108,7 +108,7 @@ public:
// Moves all artifacts from one hero to another
virtual void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) = 0;
virtual void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack) = 0;
};
class CBattleCallback : public IBattleCallback
@ -171,7 +171,7 @@ public:
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 bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap) override;
void bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped = true, bool backpack = true) override;
void eraseArtifactByClient(const ArtifactLocation & al) override;
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) override;
void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;

View File

@ -95,6 +95,7 @@ set(client_SRCS
widgets/Buttons.cpp
widgets/CArtifactHolder.cpp
widgets/CComponent.cpp
widgets/CExchangeController.cpp
widgets/CGarrisonInt.cpp
widgets/CreatureCostBox.cpp
widgets/ComboBox.cpp
@ -259,6 +260,7 @@ set(client_HEADERS
widgets/Buttons.h
widgets/CArtifactHolder.h
widgets/CComponent.h
widgets/CExchangeController.h
widgets/CGarrisonInt.h
widgets/CreatureCostBox.h
widgets/ComboBox.h

View File

@ -200,8 +200,8 @@ void CHeroArtPlace::clickPressed(const Point & cursorPosition)
void CHeroArtPlace::showPopupWindow(const Point & cursorPosition)
{
if(rightClickCallback)
rightClickCallback(*this);
if(showPopupCallback)
showPopupCallback(*this);
}
void CHeroArtPlace::showAll(Canvas & to)

View File

@ -66,11 +66,11 @@ public:
class CHeroArtPlace: public CArtPlace
{
public:
using ClickHandler = std::function<void(CHeroArtPlace&)>;
using ClickFunctor = std::function<void(CHeroArtPlace&)>;
ArtifactPosition slot;
ClickHandler leftClickCallback;
ClickHandler rightClickCallback;
ClickFunctor leftClickCallback;
ClickFunctor showPopupCallback;
CHeroArtPlace(Point position, const CArtifactInstance * Art = nullptr);
void lockSlot(bool on);

View File

@ -42,7 +42,7 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(const Point & position)
artPlace = std::make_shared<CHeroArtPlace>(pos);
artPlace->setArtifact(nullptr);
artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
artPlaceIdx++;
}

View File

@ -55,10 +55,10 @@ void CArtifactsOfHeroBase::setPutBackPickedArtifactCallback(PutBackPickedArtCall
}
void CArtifactsOfHeroBase::init(
CHeroArtPlace::ClickHandler lClickCallback,
CHeroArtPlace::ClickHandler rClickCallback,
CHeroArtPlace::ClickFunctor lClickCallback,
CHeroArtPlace::ClickFunctor showPopupCallback,
const Point & position,
BpackScrollHandler scrollHandler)
BpackScrollFunctor scrollCallback)
{
// CArtifactsOfHeroBase::init may be transform to CArtifactsOfHeroBase::CArtifactsOfHeroBase if OBJECT_CONSTRUCTION_CAPTURING is removed
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
@ -78,16 +78,16 @@ void CArtifactsOfHeroBase::init(
artPlace.second->slot = artPlace.first;
artPlace.second->setArtifact(nullptr);
artPlace.second->leftClickCallback = lClickCallback;
artPlace.second->rightClickCallback = rClickCallback;
artPlace.second->showPopupCallback = showPopupCallback;
}
for(auto artPlace : backpack)
{
artPlace->setArtifact(nullptr);
artPlace->leftClickCallback = lClickCallback;
artPlace->rightClickCallback = rClickCallback;
artPlace->showPopupCallback = showPopupCallback;
}
leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollHandler]() { scrollHandler(-1); }, EShortcut::MOVE_LEFT);
rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollHandler]() { scrollHandler(+1); }, EShortcut::MOVE_RIGHT);
leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(-1);}, EShortcut::MOVE_LEFT);
rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(), [scrollCallback]() {scrollCallback(+1);}, EShortcut::MOVE_RIGHT);
leftBackpackRoll->block(true);
rightBackpackRoll->block(true);
@ -102,8 +102,8 @@ void CArtifactsOfHeroBase::leftClickArtPlace(CHeroArtPlace & artPlace)
void CArtifactsOfHeroBase::rightClickArtPlace(CHeroArtPlace & artPlace)
{
if(rightClickCallback)
rightClickCallback(*this, artPlace);
if(showPopupCallback)
showPopupCallback(*this, artPlace);
}
void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero)

View File

@ -15,15 +15,15 @@ class CArtifactsOfHeroBase : public CIntObject
{
protected:
using ArtPlacePtr = std::shared_ptr<CHeroArtPlace>;
using BpackScrollHandler = std::function<void(int)>;
using BpackScrollFunctor = std::function<void(int)>;
public:
using ArtPlaceMap = std::map<ArtifactPosition, ArtPlacePtr>;
using ClickHandler = std::function<void(CArtifactsOfHeroBase&, CHeroArtPlace&)>;
using ClickFunctor = std::function<void(CArtifactsOfHeroBase&, CHeroArtPlace&)>;
using PutBackPickedArtCallback = std::function<void()>;
ClickHandler leftClickCallback;
ClickHandler rightClickCallback;
ClickFunctor leftClickCallback;
ClickFunctor showPopupCallback;
CArtifactsOfHeroBase();
virtual void putBackPickedArtifact();
@ -61,8 +61,8 @@ protected:
Point(381,296) //18
};
virtual void init(CHeroArtPlace::ClickHandler lClickCallback, CHeroArtPlace::ClickHandler rClickCallback,
const Point & position, BpackScrollHandler scrollHandler);
virtual void init(CHeroArtPlace::ClickFunctor lClickCallback, CHeroArtPlace::ClickFunctor showPopupCallback,
const Point & position, BpackScrollFunctor scrollCallback);
// Assigns an artifacts to an artifact place depending on it's new slot ID
virtual void setSlotData(ArtPlacePtr artPlace, const ArtifactPosition & slot, const CArtifactSet & artSet);
virtual void scrollBackpackForArtSet(int offset, const CArtifactSet & artSet);

View File

@ -29,13 +29,13 @@ CArtifactsOfHeroKingdom::CArtifactsOfHeroKingdom(ArtPlaceMap ArtWorn, std::vecto
artPlace.second->slot = artPlace.first;
artPlace.second->setArtifact(nullptr);
artPlace.second->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
artPlace.second->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
artPlace.second->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
}
for(auto artPlace : backpack)
{
artPlace->setArtifact(nullptr);
artPlace->leftClickCallback = std::bind(&CArtifactsOfHeroBase::leftClickArtPlace, this, _1);
artPlace->rightClickCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
artPlace->showPopupCallback = std::bind(&CArtifactsOfHeroBase::rightClickArtPlace, this, _1);
}
leftBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, -1));
rightBackpackRoll->addCallback(std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, +1));

View File

@ -0,0 +1,119 @@
/*
* CExchangeController.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 "CExchangeController.h"
#include "../CPlayerInterface.h"
#include "../widgets/CGarrisonInt.h"
#include "../../CCallback.h"
#include "../lib/mapObjects/CGHeroInstance.h"
CExchangeController::CExchangeController(ObjectInstanceID hero1, ObjectInstanceID hero2)
: left(LOCPLINT->cb->getHero(hero1))
, right(LOCPLINT->cb->getHero(hero2))
{
}
void CExchangeController::swapArmy()
{
auto getStacks = [](const CArmedInstance * source) -> std::vector<std::pair<SlotID, CStackInstance*>>
{
auto slots = source->Slots();
return std::vector<std::pair<SlotID, CStackInstance*>>(slots.begin(), slots.end());
};
auto leftSlots = getStacks(left);
auto rightSlots = getStacks(right);
auto i = leftSlots.begin(), j = rightSlots.begin();
for(; i != leftSlots.end() && j != rightSlots.end(); i++, j++)
{
LOCPLINT->cb->swapCreatures(left, right, i->first, j->first);
}
if(i != leftSlots.end())
{
auto freeSlots = right->getFreeSlots();
auto slot = freeSlots.begin();
for(; i != leftSlots.end() && slot != freeSlots.end(); i++, slot++)
{
LOCPLINT->cb->swapCreatures(left, right, i->first, *slot);
}
}
else if(j != rightSlots.end())
{
auto freeSlots = left->getFreeSlots();
auto slot = freeSlots.begin();
for(; j != rightSlots.end() && slot != freeSlots.end(); j++, slot++)
{
LOCPLINT->cb->swapCreatures(left, right, *slot, j->first);
}
}
}
void CExchangeController::moveArmy(bool leftToRight, std::optional<SlotID> heldSlot)
{
const auto source = leftToRight ? left : right;
const auto target = leftToRight ? right : left;
if(!heldSlot.has_value())
{
auto weakestSlot = vstd::minElementByFun(source->Slots(),
[](const std::pair<SlotID, CStackInstance*> & s) -> int
{
return s.second->getCreatureID().toCreature()->getAIValue();
});
heldSlot = weakestSlot->first;
}
LOCPLINT->cb->bulkMoveArmy(source->id, target->id, heldSlot.value());
}
void CExchangeController::moveStack(bool leftToRight, SlotID sourceSlot)
{
const auto source = leftToRight ? left : right;
const auto target = leftToRight ? right : left;
auto creature = source->getCreature(sourceSlot);
if(creature == nullptr)
return;
SlotID targetSlot = target->getSlotFor(creature);
if(targetSlot.validSlot())
{
if(source->stacksCount() == 1 && source->needsLastStack())
{
LOCPLINT->cb->splitStack(source, target, sourceSlot, targetSlot,
target->getStackCount(targetSlot) + source->getStackCount(sourceSlot) - 1);
}
else
{
LOCPLINT->cb->mergeOrSwapStacks(source, target, sourceSlot, targetSlot);
}
}
}
void CExchangeController::swapArtifacts(bool equipped, bool baclpack)
{
LOCPLINT->cb->bulkMoveArtifacts(left->id, right->id, true, equipped, baclpack);
}
void CExchangeController::moveArtifacts(bool leftToRight, bool equipped, bool baclpack)
{
const auto source = leftToRight ? left : right;
const auto target = leftToRight ? right : left;
LOCPLINT->cb->bulkMoveArtifacts(source->id, target->id, false, equipped, baclpack);
}

View File

@ -0,0 +1,30 @@
/*
* CExchangeController.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 "../windows/CWindowObject.h"
#include "CWindowWithArtifacts.h"
class CCallback;
class CExchangeController
{
public:
CExchangeController(ObjectInstanceID hero1, ObjectInstanceID hero2);
void swapArmy();
void moveArmy(bool leftToRight, std::optional<SlotID> heldSlot);
void moveStack(bool leftToRight, SlotID sourceSlot);
void swapArtifacts(bool equipped, bool baclpack);
void moveArtifacts(bool leftToRight, bool equipped, bool baclpack);
private:
const CGHeroInstance * left;
const CGHeroInstance * right;
};

View File

@ -32,18 +32,23 @@
#include "../../lib/CConfigHandler.h"
void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr artSet)
{
artSets.emplace_back(artSet);
}
void CWindowWithArtifacts::addSetAndCallbacks(CArtifactsOfHeroPtr artSet)
{
CArtifactsOfHeroBase::PutBackPickedArtCallback artPutBackHandler = []() -> void
{
CCS->curh->dragAndDropCursor(nullptr);
};
artSets.emplace_back(artSet);
addSet(artSet);
std::visit([this, artPutBackHandler](auto artSetWeak)
{
auto artSet = artSetWeak.lock();
artSet->leftClickCallback = std::bind(&CWindowWithArtifacts::leftClickArtPlaceHero, this, _1, _2);
artSet->rightClickCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2);
artSet->showPopupCallback = std::bind(&CWindowWithArtifacts::rightClickArtPlaceHero, this, _1, _2);
artSet->setPutBackPickedArtifactCallback(artPutBackHandler);
}, artSet);
}

View File

@ -28,6 +28,7 @@ public:
using CloseCallback = std::function<void()>;
void addSet(CArtifactsOfHeroPtr artSet);
void addSetAndCallbacks(CArtifactsOfHeroPtr artSet);
void addCloseCallback(CloseCallback callback);
const CGHeroInstance * getHeroPickedArtifact();
const CArtifactInstance * getPickedArtifact();
@ -39,7 +40,7 @@ public:
void artifactDisassembled(const ArtifactLocation & artLoc) override;
void artifactAssembled(const ArtifactLocation & artLoc) override;
private:
protected:
std::vector<CArtifactsOfHeroPtr> artSets;
CloseCallback closeCallback;

View File

@ -28,7 +28,7 @@ CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero)
arts = std::make_shared<CArtifactsOfHeroBackpack>(Point(windowMargin, windowMargin));
arts->setHero(hero);
addSet(arts);
addSetAndCallbacks(arts);
addCloseCallback(std::bind(&CHeroBackpackWindow::close, this));

View File

@ -219,7 +219,7 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
{
arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8));
arts->setHero(curHero);
addSet(arts);
addSetAndCallbacks(arts);
}
int serial = LOCPLINT->cb->getHeroSerial(curHero, false);

View File

@ -706,7 +706,7 @@ std::shared_ptr<CIntObject> CKingdHeroList::createHeroItem(size_t index)
if(index < heroesList.size())
{
auto hero = std::make_shared<CHeroItem>(heroesList[index]);
addSet(hero->heroArts);
addSetAndCallbacks(hero->heroArts);
return hero;
}
else

View File

@ -680,7 +680,7 @@ CMarketplaceWindow::CMarketplaceWindow(const IMarket * Market, const CGHeroInsta
arts = std::make_shared<CArtifactsOfHeroMarket>(Point(-361, 46));
arts->selectArtCallback = std::bind(&CTradeWindow::artifactSelected, this, _1);
arts->setHero(hero);
addSet(arts);
addSetAndCallbacks(arts);
}
initItems(false);
initItems(true);
@ -1133,7 +1133,7 @@ CAltarWindow::CAltarWindow(const IMarket * Market, const CGHeroInstance * Hero,
arts = std::make_shared<CArtifactsOfHeroAltar>(Point(-365, -12));
arts->setHero(hero);
addSet(arts);
addSetAndCallbacks(arts);
initItems(true);
initItems(false);

View File

@ -12,6 +12,7 @@
#include "CCastleInterface.h"
#include "CCreatureWindow.h"
#include "CHeroBackpackWindow.h"
#include "CHeroWindow.h"
#include "InfoWindows.h"
@ -19,62 +20,40 @@
#include "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../CVideoHandler.h"
#include "../CServerHandler.h"
#include "../battle/BattleInterfaceClasses.h"
#include "../battle/BattleInterface.h"
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../gui/TextAlignment.h"
#include "../gui/Shortcut.h"
#include "../gui/WindowHandler.h"
#include "../widgets/CComponent.h"
#include "../widgets/CGarrisonInt.h"
#include "../widgets/MiscWidgets.h"
#include "../widgets/CreatureCostBox.h"
#include "../widgets/Buttons.h"
#include "../widgets/Slider.h"
#include "../widgets/TextControls.h"
#include "../widgets/ObjectLists.h"
#include "../lobby/CSavingScreen.h"
#include "../render/Canvas.h"
#include "../render/CAnimation.h"
#include "../render/IRenderHandler.h"
#include "../CMT.h"
#include "../../CCallback.h"
#include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
#include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
#include "../lib/mapObjectConstructors/CommonConstructors.h"
#include "../lib/mapObjects/CGHeroInstance.h"
#include "../lib/mapObjects/CGMarket.h"
#include "../lib/ArtifactUtils.h"
#include "../lib/mapObjects/CGTownInstance.h"
#include "../lib/mapObjects/ObjectTemplate.h"
#include "../lib/gameState/CGameState.h"
#include "../lib/gameState/InfoAboutArmy.h"
#include "../lib/gameState/SThievesGuildInfo.h"
#include "../lib/CArtHandler.h"
#include "../lib/CBuildingHandler.h"
#include "../lib/CConfigHandler.h"
#include "../lib/CCreatureHandler.h"
#include "../lib/CGeneralTextHandler.h"
#include "../lib/CHeroHandler.h"
#include "../lib/GameSettings.h"
#include "../lib/CondSh.h"
#include "../lib/CSkillHandler.h"
#include "../lib/spells/CSpellHandler.h"
#include "../lib/filesystem/Filesystem.h"
#include "../lib/CStopWatch.h"
#include "../lib/CTownHandler.h"
#include "../lib/GameConstants.h"
#include "../lib/bonuses/Bonus.h"
#include "../lib/NetPacksBase.h"
#include "../lib/StartInfo.h"
#include "../lib/TextOperations.h"
CRecruitmentWindow::CCreatureCard::CCreatureCard(CRecruitmentWindow * window, const CCreature * crea, int totalAmount)
@ -623,215 +602,9 @@ static bool isQuickExchangeLayoutAvailable()
return CResourceHandler::get()->existsResource(ImagePath::builtin("SPRITES/" + QUICK_EXCHANGE_BG));
}
CExchangeController::CExchangeController(CExchangeWindow * view, ObjectInstanceID hero1, ObjectInstanceID hero2)
:left(LOCPLINT->cb->getHero(hero1)), right(LOCPLINT->cb->getHero(hero2)), cb(LOCPLINT->cb), view(view)
{
}
std::function<void()> CExchangeController::onMoveArmyToLeft()
{
return [&]() { moveArmy(false); };
}
std::function<void()> CExchangeController::onMoveArmyToRight()
{
return [&]() { moveArmy(true); };
}
std::vector<CArtifactInstance *> getBackpackArts(const CGHeroInstance * hero)
{
std::vector<CArtifactInstance *> result;
for(auto slot : hero->artifactsInBackpack)
{
result.push_back(slot.artifact);
}
return result;
}
std::function<void()> CExchangeController::onSwapArtifacts()
{
return [&]()
{
cb->bulkMoveArtifacts(left->id, right->id, true);
};
}
std::function<void()> CExchangeController::onMoveArtifactsToLeft()
{
return [&]() { moveArtifacts(false); };
}
std::function<void()> CExchangeController::onMoveArtifactsToRight()
{
return [&]() { moveArtifacts(true); };
}
std::vector<std::pair<SlotID, CStackInstance *>> getStacks(const CArmedInstance * source)
{
auto slots = source->Slots();
return std::vector<std::pair<SlotID, CStackInstance *>>(slots.begin(), slots.end());
}
std::function<void()> CExchangeController::onSwapArmy()
{
return [&]()
{
if(left->tempOwner != cb->getPlayerID()
|| right->tempOwner != cb->getPlayerID())
{
return;
}
auto leftSlots = getStacks(left);
auto rightSlots = getStacks(right);
auto i = leftSlots.begin(), j = rightSlots.begin();
for(; i != leftSlots.end() && j != rightSlots.end(); i++, j++)
{
cb->swapCreatures(left, right, i->first, j->first);
}
if(i != leftSlots.end())
{
auto freeSlots = right->getFreeSlots();
auto slot = freeSlots.begin();
for(; i != leftSlots.end() && slot != freeSlots.end(); i++, slot++)
{
cb->swapCreatures(left, right, i->first, *slot);
}
}
else if(j != rightSlots.end())
{
auto freeSlots = left->getFreeSlots();
auto slot = freeSlots.begin();
for(; j != rightSlots.end() && slot != freeSlots.end(); j++, slot++)
{
cb->swapCreatures(left, right, *slot, j->first);
}
}
};
}
std::function<void()> CExchangeController::onMoveStackToLeft(SlotID slotID)
{
return [=]()
{
if(right->tempOwner != cb->getPlayerID())
{
return;
}
moveStack(right, left, slotID);
};
}
std::function<void()> CExchangeController::onMoveStackToRight(SlotID slotID)
{
return [=]()
{
if(left->tempOwner != cb->getPlayerID())
{
return;
}
moveStack(left, right, slotID);
};
}
void CExchangeController::moveStack(
const CGHeroInstance * source,
const CGHeroInstance * target,
SlotID sourceSlot)
{
auto creature = source->getCreature(sourceSlot);
if(creature == nullptr)
return;
SlotID targetSlot = target->getSlotFor(creature);
if(targetSlot.validSlot())
{
if(source->stacksCount() == 1 && source->needsLastStack())
{
cb->splitStack(
source,
target,
sourceSlot,
targetSlot,
target->getStackCount(targetSlot) + source->getStackCount(sourceSlot) - 1);
}
else
{
cb->mergeOrSwapStacks(source, target, sourceSlot, targetSlot);
}
}
}
void CExchangeController::moveArmy(bool leftToRight)
{
const CGHeroInstance * source = leftToRight ? left : right;
const CGHeroInstance * target = leftToRight ? right : left;
const CGarrisonSlot * selection = this->view->getSelectedSlotID();
SlotID slot;
if(source->tempOwner != cb->getPlayerID())
{
return;
}
if(selection && selection->our() && selection->getObj() == source)
{
slot = selection->getSlot();
}
else
{
auto weakestSlot = vstd::minElementByFun(
source->Slots(),
[](const std::pair<SlotID, CStackInstance *> & s) -> int
{
return s.second->getCreatureID().toCreature()->getAIValue();
});
slot = weakestSlot->first;
}
cb->bulkMoveArmy(source->id, target->id, slot);
}
void CExchangeController::moveArtifacts(bool leftToRight)
{
const CGHeroInstance * source = leftToRight ? left : right;
const CGHeroInstance * target = leftToRight ? right : left;
if(source->tempOwner != cb->getPlayerID())
{
return;
}
cb->bulkMoveArtifacts(source->id, target->id, false);
}
void CExchangeController::moveArtifact(
const CGHeroInstance * source,
const CGHeroInstance * target,
ArtifactPosition srcPosition)
{
auto srcLocation = ArtifactLocation(source, srcPosition);
auto dstLocation = ArtifactLocation(target,
ArtifactUtils::getArtAnyPosition(target, source->getArt(srcPosition)->getTypeId()));
cb->swapArtifacts(srcLocation, dstLocation);
}
CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2, QueryID queryID)
: CStatusbarWindow(PLAYER_COLORED | BORDERED, ImagePath::builtin(isQuickExchangeLayoutAvailable() ? QUICK_EXCHANGE_BG : "TRADE2")),
controller(this, hero1, hero2),
controller(hero1, hero2),
moveStackLeftButtons(),
moveStackRightButtons()
{
@ -890,8 +663,8 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
artifs[1] = std::make_shared<CArtifactsOfHeroMain>(Point(98, 150));
artifs[1]->setHero(heroInst[1]);
addSet(artifs[0]);
addSet(artifs[1]);
addSetAndCallbacks(artifs[0]);
addSetAndCallbacks(artifs[1]);
for(int g=0; g<4; ++g)
{
@ -982,12 +755,62 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
if(qeLayout)
{
moveAllGarrButtonLeft = std::make_shared<CButton>(Point(325, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]), controller.onMoveArmyToRight());
echangeGarrButton = std::make_shared<CButton>(Point(377, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[2]), controller.onSwapArmy());
moveAllGarrButtonRight = std::make_shared<CButton>(Point(425, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]), controller.onMoveArmyToLeft());
moveArtifactsButtonLeft = std::make_shared<CButton>(Point(325, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]), controller.onMoveArtifactsToRight());
echangeArtifactsButton = std::make_shared<CButton>(Point(377, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[4]), controller.onSwapArtifacts());
moveArtifactsButtonRight = std::make_shared<CButton>(Point(425, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]), controller.onMoveArtifactsToLeft());
auto moveArtifacts = [](const std::function<void(bool, bool)> moveRoutine) -> void
{
bool moveEquipped = true;
bool moveBackpack = true;
if(GH.isKeyboardCtrlDown())
moveBackpack = false;
else if(GH.isKeyboardShiftDown())
moveEquipped = false;
moveRoutine(moveEquipped, moveBackpack);
};
auto moveArmy = [this](const bool leftToRight) -> void
{
std::optional<SlotID> slotId = std::nullopt;
if(auto slot = getSelectedSlotID())
slotId = slot->getSlot();
controller.moveArmy(leftToRight, slotId);
};
auto openBackpack = [this](const CGHeroInstance * hero) -> void
{
GH.windows().createAndPushWindow<CHeroBackpackWindow>(hero);
for(auto artSet : artSets)
GH.windows().topWindow<CHeroBackpackWindow>()->addSet(artSet);
};
moveAllGarrButtonLeft = std::make_shared<CButton>(Point(325, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
std::bind(moveArmy, true));
exchangeGarrButton = std::make_shared<CButton>(Point(377, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[2]),
std::bind(&CExchangeController::swapArmy, &controller));
moveAllGarrButtonRight = std::make_shared<CButton>(Point(425, 118), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/armLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
std::bind(moveArmy, false));
moveArtifactsButtonLeft = std::make_shared<CButton>(Point(325, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artRight.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]),
std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.moveArtifacts(true, equipped, baclpack);}));
exchangeArtifactsButton = std::make_shared<CButton>(Point(377, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/swapAll.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[4]),
std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.swapArtifacts(equipped, baclpack);}));
moveArtifactsButtonRight = std::make_shared<CButton>(Point(425, 154), AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/artLeft.DEF"), CButton::tooltip(CGI->generaltexth->qeModCommands[3]),
std::bind(moveArtifacts, [this](bool equipped, bool baclpack) -> void {controller.moveArtifacts(false, equipped, baclpack);}));
backpackButtonLeft = std::make_shared<CButton>(Point(325, 518), AnimationPath::builtin("buttons/backpack"), CButton::tooltipLocalized("vcmi.heroWindow.openBackpack"),
std::bind(openBackpack, heroInst[0]));
backpackButtonLeft->addOverlay(std::make_shared<CPicture>(ImagePath::builtin("buttons/backpackButtonIcon")));
backpackButtonRight = std::make_shared<CButton>(Point(419, 518), AnimationPath::builtin("buttons/backpack"), CButton::tooltipLocalized("vcmi.heroWindow.openBackpack"),
std::bind(openBackpack, heroInst[1]));
backpackButtonRight->addOverlay(std::make_shared<CPicture>(ImagePath::builtin("buttons/backpackButtonIcon")));
auto leftHeroBlock = heroInst[0]->tempOwner != LOCPLINT->cb->getPlayerID();
auto rightHeroBlock = heroInst[1]->tempOwner != LOCPLINT->cb->getPlayerID();
moveAllGarrButtonLeft->block(leftHeroBlock);
exchangeGarrButton->block(leftHeroBlock || rightHeroBlock);
moveAllGarrButtonRight->block(rightHeroBlock);
moveArtifactsButtonLeft->block(leftHeroBlock);
exchangeArtifactsButton->block(leftHeroBlock || rightHeroBlock);
moveArtifactsButtonRight->block(rightHeroBlock);
backpackButtonLeft->block(leftHeroBlock);
backpackButtonRight->block(rightHeroBlock);
for(int i = 0; i < GameConstants::ARMY_SIZE; i++)
{
@ -996,14 +819,16 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
Point(484 + 35 * i, 154),
AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/unitLeft.DEF"),
CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
controller.onMoveStackToLeft(SlotID(i))));
std::bind(&CExchangeController::moveStack, &controller, false, SlotID(i))));
moveStackLeftButtons.back()->block(leftHeroBlock);
moveStackRightButtons.push_back(
std::make_shared<CButton>(
Point(66 + 35 * i, 154),
AnimationPath::builtin(QUICK_EXCHANGE_MOD_PREFIX + "/unitRight.DEF"),
CButton::tooltip(CGI->generaltexth->qeModCommands[1]),
controller.onMoveStackToRight(SlotID(i))));
std::bind(&CExchangeController::moveStack, &controller, true, SlotID(i))));
moveStackLeftButtons.back()->block(rightHeroBlock);
}
}

View File

@ -9,10 +9,8 @@
*/
#pragma once
#include "CWindowObject.h"
#include "../lib/GameConstants.h"
#include "../lib/ResourceSet.h"
#include "../lib/int3.h"
#include "../widgets/CExchangeController.h"
#include "../widgets/CWindowWithArtifacts.h"
#include "../widgets/Images.h"
@ -28,16 +26,13 @@ class CreatureCostBox;
class CCreaturePic;
class MoraleLuckBox;
class CHeroArea;
class CMinorResDataBar;
class CSlider;
class CComponentBox;
class CTextInput;
class CListBox;
class CLabelGroup;
class CToggleButton;
class CGStatusBar;
class CTextBox;
class CResDataBar;
class CGarrisonInt;
class CGarrisonSlot;
@ -246,35 +241,6 @@ public:
void show(Canvas & to) override;
};
class CCallback;
class CExchangeWindow;
class CExchangeController
{
private:
const CGHeroInstance * left;
const CGHeroInstance * right;
std::shared_ptr<CCallback> cb;
CExchangeWindow * view;
public:
CExchangeController(CExchangeWindow * view, ObjectInstanceID hero1, ObjectInstanceID hero2);
std::function<void()> onMoveArmyToRight();
std::function<void()> onSwapArmy();
std::function<void()> onMoveArmyToLeft();
std::function<void()> onSwapArtifacts();
std::function<void()> onMoveArtifactsToLeft();
std::function<void()> onMoveArtifactsToRight();
std::function<void()> onMoveStackToLeft(SlotID slotID);
std::function<void()> onMoveStackToRight(SlotID slotID);
private:
void moveArmy(bool leftToRight);
void moveArtifacts(bool leftToRight);
void moveArtifact(const CGHeroInstance * source, const CGHeroInstance * target, ArtifactPosition srcPosition);
void moveStack(const CGHeroInstance * source, const CGHeroInstance * target, SlotID sourceSlot);
};
class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public CWindowWithArtifacts
{
std::array<std::shared_ptr<CLabel>, 2> titles;
@ -303,13 +269,15 @@ class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public
std::shared_ptr<CGarrisonInt> garr;
std::shared_ptr<CButton> moveAllGarrButtonLeft;
std::shared_ptr<CButton> echangeGarrButton;
std::shared_ptr<CButton> exchangeGarrButton;
std::shared_ptr<CButton> moveAllGarrButtonRight;
std::shared_ptr<CButton> moveArtifactsButtonLeft;
std::shared_ptr<CButton> echangeArtifactsButton;
std::shared_ptr<CButton> exchangeArtifactsButton;
std::shared_ptr<CButton> moveArtifactsButtonRight;
std::vector<std::shared_ptr<CButton>> moveStackLeftButtons;
std::vector<std::shared_ptr<CButton>> moveStackRightButtons;
std::shared_ptr<CButton> backpackButtonLeft;
std::shared_ptr<CButton> backpackButtonRight;
CExchangeController controller;
public:

View File

@ -170,7 +170,6 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa
auto * artInst = new CArtifactInstance(art);
if(art->isCombined())
{
assert(art->isCombined());
for(const auto & part : art->getConstituents())
artInst->addPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST);
}

View File

@ -9,7 +9,6 @@
*/
#include "StdInc.h"
#include "CArtHandler.h"
#include "ArtifactUtils.h"
#include "CGeneralTextHandler.h"
@ -925,8 +924,10 @@ unsigned CArtifactSet::getArtPosCount(const ArtifactID & aid, bool onlyWorn, boo
return 0;
}
void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art)
CArtifactSet::ArtPlacementMap CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art)
{
ArtPlacementMap resArtPlacement;
setNewArtSlot(slot, art, false);
if(art->artType->isCombined() && ArtifactUtils::isSlotEquipment(slot))
{
@ -939,18 +940,25 @@ void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art)
break;
}
for(auto & part : art->getPartsInfo())
for(const auto & part : art->getPartsInfo())
{
if(part.art != mainPart)
{
if(!part.art->artType->canBePutAt(this, part.slot))
part.slot = ArtifactUtils::getArtAnyPosition(this, part.art->getTypeId());
auto partSlot = part.slot;
if(!part.art->artType->canBePutAt(this, partSlot))
partSlot = ArtifactUtils::getArtAnyPosition(this, part.art->getTypeId());
assert(ArtifactUtils::isSlotEquipment(part.slot));
setNewArtSlot(part.slot, part.art, true);
assert(ArtifactUtils::isSlotEquipment(partSlot));
setNewArtSlot(partSlot, part.art, true);
resArtPlacement.emplace(std::make_pair(part.art, partSlot));
}
else
{
resArtPlacement.emplace(std::make_pair(part.art, part.slot));
}
}
}
return resArtPlacement;
}
void CArtifactSet::removeArtifact(ArtifactPosition slot)
@ -1031,7 +1039,7 @@ bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockChe
return true; //no slot means not used
}
void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked)
void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked)
{
assert(!vstd::contains(artifactsWorn, slot));

View File

@ -246,11 +246,13 @@ struct DLL_LINKAGE ArtSlotInfo
class DLL_LINKAGE CArtifactSet
{
public:
using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>;
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
std::map<ArtifactPosition, ArtSlotInfo> artifactsWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
std::vector<ArtSlotInfo> artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange
void setNewArtSlot(const ArtifactPosition & slot, CArtifactInstance * art, bool locked);
void setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked);
void eraseArtSlot(const ArtifactPosition & slot);
const ArtSlotInfo * getSlot(const ArtifactPosition & pos) const;
@ -275,7 +277,7 @@ public:
unsigned getArtPosCount(const ArtifactID & aid, bool onlyWorn = true, bool searchBackpackAssemblies = true, bool allowLocked = true) const;
virtual ArtBearer::ArtBearer bearerType() const = 0;
virtual void putArtifact(ArtifactPosition slot, CArtifactInstance * art);
virtual ArtPlacementMap putArtifact(ArtifactPosition slot, CArtifactInstance * art);
virtual void removeArtifact(ArtifactPosition slot);
virtual ~CArtifactSet();

View File

@ -44,17 +44,21 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c
return false;
}
std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstance::getPartsInfo()
{
// TODO romove this func. encapsulation violation
return partsInfo;
}
const std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstance::getPartsInfo() const
{
return partsInfo;
}
void CCombinedArtifactInstance::addPlacementMap(CArtifactSet::ArtPlacementMap & placementMap)
{
if(!placementMap.empty())
for(auto & part : partsInfo)
{
assert(placementMap.find(part.art) != placementMap.end());
part.slot = placementMap.at(part.art);
}
}
SpellID CScrollArtifactInstance::getScrollSpellID() const
{
auto artInst = static_cast<const CArtifactInstance*>(this);
@ -163,7 +167,8 @@ bool CArtifactInstance::isCombined() const
void CArtifactInstance::putAt(const ArtifactLocation & al)
{
al.getHolderArtSet()->putArtifact(al.slot, this);
auto placementMap = al.getHolderArtSet()->putArtifact(al.slot, this);
addPlacementMap(placementMap);
}
void CArtifactInstance::removeFrom(const ArtifactLocation & al)

View File

@ -12,6 +12,7 @@
#include "bonuses/CBonusSystemNode.h"
#include "GameConstants.h"
#include "ConstTransitivePtr.h"
#include "CArtHandler.h"
VCMI_LIB_NAMESPACE_BEGIN
@ -37,8 +38,8 @@ public:
void addPart(CArtifactInstance * art, const ArtifactPosition & slot);
// Checks if supposed part inst is part of this combined art inst
bool isPart(const CArtifactInstance * supposedPart) const;
std::vector<PartInfo> & getPartsInfo();
const std::vector<PartInfo> & getPartsInfo() const;
void addPlacementMap(CArtifactSet::ArtPlacementMap & placementMap);
template <typename Handler> void serialize(Handler & h, const int version)
{

View File

@ -868,14 +868,13 @@ ArtBearer::ArtBearer CStackInstance::bearerType() const
return ArtBearer::CREATURE;
}
void CStackInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
CStackInstance::ArtPlacementMap CStackInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
{
assert(!getArt(pos));
assert(art->artType->canBePutAt(this, pos));
CArtifactSet::putArtifact(pos, art);
if(ArtifactUtils::isSlotEquipment(pos))
attachTo(*art);
return CArtifactSet::putArtifact(pos, art);
}
void CStackInstance::removeArtifact(ArtifactPosition pos)

View File

@ -121,7 +121,7 @@ public:
void setArmyObj(const CArmedInstance *ArmyObj);
virtual void giveStackExp(TExpType exp);
bool valid(bool allowUnrandomized) const;
void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;//from CArtifactSet
ArtPlacementMap putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;//from CArtifactSet
void removeArtifact(ArtifactPosition pos) override;
ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet
virtual std::string nodeName() const override; //from CBonusSystemnode

View File

@ -2439,12 +2439,16 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer
ObjectInstanceID srcHero;
ObjectInstanceID dstHero;
bool swap = false;
bool equipped = true;
bool backpack = true;
BulkExchangeArtifacts() = default;
BulkExchangeArtifacts(const ObjectInstanceID & srcHero, const ObjectInstanceID & dstHero, bool swap)
BulkExchangeArtifacts(const ObjectInstanceID & srcHero, const ObjectInstanceID & dstHero, bool swap, bool equipped, bool backpack)
: srcHero(srcHero)
, dstHero(dstHero)
, swap(swap)
, equipped(equipped)
, backpack(backpack)
{
}
@ -2456,6 +2460,8 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer
h & srcHero;
h & dstHero;
h & swap;
h & equipped;
h & backpack;
}
};

View File

@ -1066,13 +1066,13 @@ std::string CGHeroInstance::getBiographyTextID() const
return "";
}
void CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance *art)
CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
{
assert(art->artType->canBePutAt(this, pos));
CArtifactSet::putArtifact(pos, art);
if(ArtifactUtils::isSlotEquipment(pos))
attachTo(*art);
return CArtifactSet::putArtifact(pos, art);
}
void CGHeroInstance::removeArtifact(ArtifactPosition pos)

View File

@ -229,7 +229,7 @@ public:
void initHero(CRandomGenerator & rand);
void initHero(CRandomGenerator & rand, const HeroTypeID & SUBID);
void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
ArtPlacementMap putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
void removeArtifact(ArtifactPosition pos) override;
void initExp(CRandomGenerator & rand);
void initArmy(CRandomGenerator & rand, IArmyDescriptor *dst = nullptr);

View File

@ -492,7 +492,7 @@ void CMap::checkForObjectives()
}
}
void CMap::addNewArtifactInstance(CArtifactInstance * art)
void CMap::addNewArtifactInstance(ConstTransitivePtr<CArtifactInstance> art)
{
art->setId(static_cast<ArtifactInstanceID>(artInstances.size()));
artInstances.emplace_back(art);

View File

@ -94,7 +94,7 @@ public:
void removeBlockVisTiles(CGObjectInstance * obj, bool total = false);
void calculateGuardingGreaturePositions();
void addNewArtifactInstance(CArtifactInstance * art);
void addNewArtifactInstance(ConstTransitivePtr<CArtifactInstance> art);
void eraseArtifactInstance(CArtifactInstance * art);
void addNewQuestInstance(CQuest * quest);

View File

@ -941,10 +941,10 @@ bool CMapLoaderH3M::loadArtifactToSlot(CGHeroInstance * hero, int slot)
// He has Shackles of War (normally - MISC slot artifact) in LEFT_HAND slot set in editor
// Artifact seems to be missing in game, so skip artifacts that don't fit target slot
auto * artifact = ArtifactUtils::createArtifact(map, artifactID);
auto artifactPos = ArtifactPosition(slot);
if(artifact->canBePutAt(ArtifactLocation(hero, artifactPos)))
auto dstLoc = ArtifactLocation(hero, ArtifactPosition(slot));
if(artifact->canBePutAt(dstLoc))
{
hero->putArtifact(artifactPos, artifact);
artifact->putAt(dstLoc);
}
else
{

View File

@ -2744,7 +2744,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
return true;
}
bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap)
bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack)
{
// Make sure exchange is even possible between the two heroes.
if(!isAllowedExchange(srcHero, dstHero))
@ -2799,21 +2799,28 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
slots.push_back(BulkMoveArtifacts::LinkedSlots(slot, slot));
}
};
if(equipped)
{
// Move over artifacts that are worn srcHero -> dstHero
moveArtsWorn(psrcHero, pdstHero, slotsSrcDst);
artFittingSet.artifactsWorn.clear();
// Move over artifacts that are worn dstHero -> srcHero
moveArtsWorn(pdstHero, psrcHero, slotsDstSrc);
}
if(backpack)
{
// Move over artifacts that are in backpack srcHero -> dstHero
moveArtsInBackpack(psrcHero, slotsSrcDst);
// Move over artifacts that are in backpack dstHero -> srcHero
moveArtsInBackpack(pdstHero, slotsDstSrc);
}
}
else
{
artFittingSet.artifactsInBackpack = pdstHero->artifactsInBackpack;
artFittingSet.artifactsWorn = pdstHero->artifactsWorn;
if(equipped)
{
// Move over artifacts that are worn
for(auto & artInfo : psrcHero->artifactsWorn)
{
@ -2822,6 +2829,9 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
moveArtifact(psrcHero->getArt(artInfo.first), artInfo.first, pdstHero, slotsSrcDst);
}
}
}
if(backpack)
{
// Move over artifacts that are in backpack
for(auto & slotInfo : psrcHero->artifactsInBackpack)
{
@ -2829,6 +2839,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
psrcHero->getArtPos(slotInfo.artifact), pdstHero, slotsSrcDst);
}
}
}
sendAndApply(&ma);
return true;
}

View File

@ -131,7 +131,7 @@ public:
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override;
void removeArtifact(const ArtifactLocation &al) override;
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override;
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap);
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack);
bool eraseArtifactByClient(const ArtifactLocation & al);
void synchronizeArtifactHandlerLists();

View File

@ -68,7 +68,7 @@ void ApplyGhNetPackVisitor::visitArrangeStacks(ArrangeStacks & pack)
void ApplyGhNetPackVisitor::visitBulkMoveArmy(BulkMoveArmy & pack)
{
gh.throwIfWrongPlayer(&pack);
gh.throwIfWrongOwner(&pack, pack.srcArmy);
result = gh.bulkMoveArmy(pack.srcArmy, pack.destArmy, pack.srcSlot);
}
@ -132,7 +132,9 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
{
gh.throwIfWrongOwner(&pack, pack.srcHero);
result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap);
if(pack.swap)
gh.throwIfWrongOwner(&pack, pack.dstHero);
result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack);
}
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)