1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-01-12 02:28:11 +02:00

Merge pull request #3656 from SoundSSGood/backpack-management

Backpack management init
This commit is contained in:
Ivan Savenko 2024-03-24 19:09:32 +02:00 committed by GitHub
commit 6a5696604e
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
27 changed files with 182 additions and 95 deletions

View File

@ -180,6 +180,14 @@ void CCallback::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dst
sendRequest(&bma);
}
void CCallback::scrollBackpackArtifacts(ObjectInstanceID hero, bool left)
{
ManageBackpackArtifacts mba(hero, ManageBackpackArtifacts::ManageCmd::SCROLL_RIGHT);
if(left)
mba.cmd = ManageBackpackArtifacts::ManageCmd::SCROLL_LEFT;
sendRequest(&mba);
}
void CCallback::eraseArtifactByClient(const ArtifactLocation & al)
{
EraseArtifactByClient ea(al);

View File

@ -90,6 +90,7 @@ public:
virtual int splitStack(const CArmedInstance *s1, const CArmedInstance *s2, SlotID p1, SlotID p2, int val)=0;//split creatures from the first stack
//virtual bool swapArtifacts(const CGHeroInstance * hero1, ui16 pos1, const CGHeroInstance * hero2, ui16 pos2)=0; //swaps artifacts between two given heroes
virtual bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2)=0;
virtual void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) = 0;
virtual void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo)=0;
virtual void eraseArtifactByClient(const ArtifactLocation & al)=0;
virtual bool dismissCreature(const CArmedInstance *obj, SlotID stackPos)=0;
@ -174,6 +175,7 @@ public:
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, bool equipped = true, bool backpack = true) override;
void scrollBackpackArtifacts(ObjectInstanceID hero, bool left) 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

@ -191,7 +191,7 @@ public:
bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) override {return false;}
bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override {return false;};
void removeArtifact(const ArtifactLocation & al) override {};
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;};
bool moveArtifact(const PlayerColor & player, const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;};
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {};
void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero) override {};

View File

@ -290,8 +290,8 @@ void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack)
callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst);
};
moveArtifact(cl.getOwner(pack.src.artHolder));
if(cl.getOwner(pack.src.artHolder) != cl.getOwner(pack.dst.artHolder))
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
@ -305,7 +305,7 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
{
auto srcLoc = ArtifactLocation(pack.srcArtHolder, slotToMove.srcPos);
auto dstLoc = ArtifactLocation(pack.dstArtHolder, slotToMove.dstPos);
MoveArtifact ma(&srcLoc, &dstLoc, pack.askAssemble);
MoveArtifact ma(pack.interfaceOwner, srcLoc, dstLoc, pack.askAssemble);
visitMoveArtifact(ma);
}
};

View File

@ -25,7 +25,7 @@ CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position)
std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2),
std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2),
position,
std::bind(&CArtifactsOfHeroAltar::scrollBackpack, this, _1));
std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
// The backpack is in the altar window above and to the right
for(auto & slot : backpack)

View File

@ -26,6 +26,7 @@
CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax)
: slotsColumnsMax(slotsColumnsMax)
, slotsRowsMax(slotsRowsMax)
, backpackPos(0)
{
setRedrawParent(true);
}
@ -41,11 +42,11 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack()
initAOHbackpack(visibleCapacityMax, backpackCap < 0 || visibleCapacityMax < backpackCap);
}
void CArtifactsOfHeroBackpack::scrollBackpack(int offset)
void CArtifactsOfHeroBackpack::onSliderMoved(int newVal)
{
if(backpackListBox)
backpackListBox->resize(getActiveSlotRowsNum());
backpackPos += offset;
backpackPos += newVal;
auto slot = ArtifactPosition::BACKPACK_START + backpackPos;
for(auto artPlace : backpack)
{
@ -98,7 +99,7 @@ void CArtifactsOfHeroBackpack::initAOHbackpack(size_t slots, bool slider)
};
CListBoxWithCallback::MovedPosCallback posMoved = [this](size_t pos) -> void
{
scrollBackpack(static_cast<int>(pos) * slotsColumnsMax - backpackPos);
onSliderMoved(static_cast<int>(pos) * slotsColumnsMax - backpackPos);
};
backpackListBox = std::make_shared<CListBoxWithCallback>(
posMoved, onCreate, Point(0, 0), Point(0, 0), slotsRowsMax, 0, 0, 1,

View File

@ -24,7 +24,7 @@ class CArtifactsOfHeroBackpack : public CArtifactsOfHeroBase
public:
CArtifactsOfHeroBackpack(size_t slotsColumnsMax, size_t slotsRowsMax);
CArtifactsOfHeroBackpack();
void scrollBackpack(int offset) override;
void onSliderMoved(int newVal);
void updateBackpackSlots() override;
size_t getActiveSlotRowsNum();
size_t getSlotsNum();
@ -36,6 +36,7 @@ protected:
size_t slotsRowsMax;
const int slotSizeWithMargin = 46;
const int sliderPosOffsetX = 5;
int backpackPos; // Position to display artifacts in heroes backpack
void initAOHbackpack(size_t slots, bool slider);
size_t calcRows(size_t slots);

View File

@ -25,8 +25,7 @@
#include "../../lib/networkPacks/ArtifactLocation.h"
CArtifactsOfHeroBase::CArtifactsOfHeroBase()
: backpackPos(0),
curHero(nullptr),
: curHero(nullptr),
putBackPickedArtCallback(nullptr)
{
}
@ -56,10 +55,10 @@ void CArtifactsOfHeroBase::setPutBackPickedArtifactCallback(PutBackPickedArtCall
}
void CArtifactsOfHeroBase::init(
CArtPlace::ClickFunctor lClickCallback,
CArtPlace::ClickFunctor showPopupCallback,
const CArtPlace::ClickFunctor & onClickPressedCallback,
const CArtPlace::ClickFunctor & onShowPopupCallback,
const Point & position,
BpackScrollFunctor scrollCallback)
const BpackScrollFunctor & scrollCallback)
{
// CArtifactsOfHeroBase::init may be transform to CArtifactsOfHeroBase::CArtifactsOfHeroBase if OBJECT_CONSTRUCTION_CAPTURING is removed
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);
@ -78,17 +77,19 @@ void CArtifactsOfHeroBase::init(
{
artPlace.second->slot = artPlace.first;
artPlace.second->setArtifact(nullptr);
artPlace.second->setClickPressedCallback(lClickCallback);
artPlace.second->setShowPopupCallback(showPopupCallback);
artPlace.second->setClickPressedCallback(onClickPressedCallback);
artPlace.second->setShowPopupCallback(onShowPopupCallback);
}
for(auto artPlace : backpack)
{
artPlace->setArtifact(nullptr);
artPlace->setClickPressedCallback(lClickCallback);
artPlace->setShowPopupCallback(showPopupCallback);
artPlace->setClickPressedCallback(onClickPressedCallback);
artPlace->setShowPopupCallback(onShowPopupCallback);
}
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 = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(),
[scrollCallback](){scrollCallback(true);}, EShortcut::MOVE_LEFT);
rightBackpackRoll = std::make_shared<CButton>(Point(632, 364), AnimationPath::builtin("hsbtns5.def"), CButton::tooltip(),
[scrollCallback](){scrollCallback(false);}, EShortcut::MOVE_RIGHT);
leftBackpackRoll->block(true);
rightBackpackRoll->block(true);
@ -116,16 +117,12 @@ void CArtifactsOfHeroBase::gestureArtPlace(CArtPlace & artPlace, const Point & c
void CArtifactsOfHeroBase::setHero(const CGHeroInstance * hero)
{
curHero = hero;
if(curHero->artifactsInBackpack.size() > 0)
backpackPos %= curHero->artifactsInBackpack.size();
else
backpackPos = 0;
for(auto slot : artWorn)
{
setSlotData(slot.second, slot.first);
}
scrollBackpack(0);
updateBackpackSlots();
}
const CGHeroInstance * CArtifactsOfHeroBase::getHero() const
@ -133,48 +130,9 @@ const CGHeroInstance * CArtifactsOfHeroBase::getHero() const
return curHero;
}
void CArtifactsOfHeroBase::scrollBackpack(int offset)
void CArtifactsOfHeroBase::scrollBackpack(bool left)
{
// offset==-1 => to left; offset==1 => to right
using slotInc = std::function<ArtifactPosition(ArtifactPosition&)>;
auto artsInBackpack = static_cast<int>(curHero->artifactsInBackpack.size());
auto scrollingPossible = artsInBackpack > backpack.size();
slotInc inc_straight = [](ArtifactPosition & slot) -> ArtifactPosition
{
return slot + 1;
};
slotInc inc_ring = [artsInBackpack](ArtifactPosition & slot) -> ArtifactPosition
{
return ArtifactPosition::BACKPACK_START + (slot - ArtifactPosition::BACKPACK_START + 1) % artsInBackpack;
};
slotInc inc;
if(scrollingPossible)
inc = inc_ring;
else
inc = inc_straight;
backpackPos += offset;
if(backpackPos < 0)
backpackPos += artsInBackpack;
if(artsInBackpack)
backpackPos %= artsInBackpack;
auto slot = ArtifactPosition(ArtifactPosition::BACKPACK_START + backpackPos);
for(auto artPlace : backpack)
{
setSlotData(artPlace, slot);
slot = inc(slot);
}
// Blocking scrolling if there is not enough artifacts to scroll
if(leftBackpackRoll)
leftBackpackRoll->block(!scrollingPossible);
if(rightBackpackRoll)
rightBackpackRoll->block(!scrollingPossible);
redraw();
LOCPLINT->cb->scrollBackpackArtifacts(curHero->id, left);
}
void CArtifactsOfHeroBase::markPossibleSlots(const CArtifactInstance * art, bool assumeDestRemoved)
@ -224,9 +182,18 @@ void CArtifactsOfHeroBase::updateWornSlots()
void CArtifactsOfHeroBase::updateBackpackSlots()
{
if(curHero->artifactsInBackpack.size() <= backpack.size() && backpackPos != 0)
backpackPos = 0;
scrollBackpack(0);
ArtifactPosition slot = ArtifactPosition::BACKPACK_START;
for(const auto & artPlace : backpack)
{
setSlotData(artPlace, slot);
slot = slot + 1;
}
auto scrollingPossible = static_cast<int>(curHero->artifactsInBackpack.size()) > backpack.size();
// Blocking scrolling if there is not enough artifacts to scroll
if(leftBackpackRoll)
leftBackpackRoll->block(!scrollingPossible);
if(rightBackpackRoll)
rightBackpackRoll->block(!scrollingPossible);
}
void CArtifactsOfHeroBase::updateSlot(const ArtifactPosition & slot)

View File

@ -36,7 +36,7 @@ public:
virtual void gestureArtPlace(CArtPlace & artPlace, const Point & cursorPosition);
virtual void setHero(const CGHeroInstance * hero);
virtual const CGHeroInstance * getHero() const;
virtual void scrollBackpack(int offset);
virtual void scrollBackpack(bool left);
virtual void markPossibleSlots(const CArtifactInstance * art, bool assumeDestRemoved = true);
virtual void unmarkSlots();
virtual ArtPlacePtr getArtPlace(const ArtifactPosition & slot);
@ -52,7 +52,6 @@ protected:
std::vector<ArtPlacePtr> backpack;
std::shared_ptr<CButton> leftBackpackRoll;
std::shared_ptr<CButton> rightBackpackRoll;
int backpackPos; // Position to display artifacts in heroes backpack
PutBackPickedArtCallback putBackPickedArtCallback;
const std::vector<Point> slotPos =
@ -66,8 +65,8 @@ protected:
Point(381,295) //18
};
virtual void init(CHeroArtPlace::ClickFunctor lClickCallback, CHeroArtPlace::ClickFunctor showPopupCallback,
const Point & position, BpackScrollFunctor scrollCallback);
virtual void init(const CHeroArtPlace::ClickFunctor & lClickCallback, const CHeroArtPlace::ClickFunctor & showPopupCallback,
const Point & position, const BpackScrollFunctor & scrollCallback);
// Assigns an artifacts to an artifact place depending on it's new slot ID
virtual void setSlotData(ArtPlacePtr artPlace, const ArtifactPosition & slot);
};

View File

@ -18,7 +18,7 @@ CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position)
std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2),
std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2),
position,
std::bind(&CArtifactsOfHeroMarket::scrollBackpack, this, _1));
std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
for(const auto & [slot, artPlace] : artWorn)
artPlace->setSelectionWidth(2);
@ -26,9 +26,9 @@ CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position)
artPlace->setSelectionWidth(2);
};
void CArtifactsOfHeroMarket::scrollBackpack(int offset)
void CArtifactsOfHeroMarket::scrollBackpack(bool left)
{
CArtifactsOfHeroBase::scrollBackpack(offset);
CArtifactsOfHeroBase::scrollBackpack(left);
// We may have highlight on one of backpack artifacts
if(selectArtCallback)

View File

@ -17,5 +17,5 @@ public:
std::function<void(CArtPlace*)> selectArtCallback;
CArtifactsOfHeroMarket(const Point & position);
void scrollBackpack(int offset) override;
void scrollBackpack(bool left) override;
};

View File

@ -145,7 +145,11 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(CArtifactsOfHeroBase & artsI
if(artSetPtr->getHero()->getOwner() == LOCPLINT->playerID)
{
if(checkSpecialArts(*art, hero, std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroAltar>> ? true : false))
LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot), ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS));
{
assert(artSetPtr->getHero()->getSlotByInstance(art));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artSetPtr->getHero()->getSlotByInstance(art)),
ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS));
}
}
else
{

View File

@ -192,7 +192,7 @@ class DLL_LINKAGE CArtifactSet
public:
using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>;
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag
std::deque<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

View File

@ -110,7 +110,7 @@ public:
virtual bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) = 0;
virtual bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble = std::nullopt) = 0;
virtual void removeArtifact(const ArtifactLocation &al) = 0;
virtual bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) = 0;
virtual bool moveArtifact(const PlayerColor & player, const ArtifactLocation & al1, const ArtifactLocation & al2) = 0;
virtual void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero)=0;
virtual void visitCastleObjects(const CGTownInstance * obj, const CGHeroInstance * hero)=0;

View File

@ -131,6 +131,7 @@ public:
virtual void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) {}
virtual void visitExchangeArtifacts(ExchangeArtifacts & pack) {}
virtual void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) {}
virtual void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) {}
virtual void visitAssembleArtifacts(AssembleArtifacts & pack) {}
virtual void visitEraseArtifactByClient(EraseArtifactByClient & pack) {}
virtual void visitBuyArtifact(BuyArtifact & pack) {}

View File

@ -608,6 +608,11 @@ void BulkExchangeArtifacts::visitTyped(ICPackVisitor & visitor)
visitor.visitBulkExchangeArtifacts(*this);
}
void ManageBackpackArtifacts::visitTyped(ICPackVisitor & visitor)
{
visitor.visitManageBackpackArtifacts(*this);
}
void AssembleArtifacts::visitTyped(ICPackVisitor & visitor)
{
visitor.visitAssembleArtifacts(*this);

View File

@ -1030,10 +1030,11 @@ struct DLL_LINKAGE EraseArtifact : CArtifactOperationPack
struct DLL_LINKAGE MoveArtifact : CArtifactOperationPack
{
MoveArtifact() = default;
MoveArtifact(ArtifactLocation * src, ArtifactLocation * dst, bool askAssemble = true)
: src(*src), dst(*dst), askAssemble(askAssemble)
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;
@ -1043,6 +1044,7 @@ struct DLL_LINKAGE MoveArtifact : CArtifactOperationPack
template <typename Handler> void serialize(Handler & h)
{
h & interfaceOwner;
h & src;
h & dst;
h & askAssemble;
@ -1069,13 +1071,15 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
}
};
PlayerColor interfaceOwner;
ObjectInstanceID srcArtHolder;
ObjectInstanceID dstArtHolder;
std::optional<SlotID> srcCreature;
std::optional<SlotID> dstCreature;
BulkMoveArtifacts()
: srcArtHolder(ObjectInstanceID::NONE)
: interfaceOwner(PlayerColor::NEUTRAL)
, srcArtHolder(ObjectInstanceID::NONE)
, dstArtHolder(ObjectInstanceID::NONE)
, swap(false)
, askAssemble(false)
@ -1083,9 +1087,10 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
, dstCreature(std::nullopt)
{
}
BulkMoveArtifacts(const ObjectInstanceID srcArtHolder, const ObjectInstanceID dstArtHolder, bool swap)
: srcArtHolder(std::move(srcArtHolder))
, dstArtHolder(std::move(dstArtHolder))
BulkMoveArtifacts(const PlayerColor & interfaceOwner, const ObjectInstanceID srcArtHolder, const ObjectInstanceID dstArtHolder, bool swap)
: interfaceOwner(interfaceOwner)
, srcArtHolder(srcArtHolder)
, dstArtHolder(dstArtHolder)
, swap(swap)
, askAssemble(false)
, srcCreature(std::nullopt)
@ -1104,6 +1109,7 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
template <typename Handler> void serialize(Handler & h)
{
h & interfaceOwner;
h & artsPack0;
h & artsPack1;
h & srcArtHolder;

View File

@ -401,6 +401,33 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer
}
};
struct DLL_LINKAGE ManageBackpackArtifacts : public CPackForServer
{
enum class ManageCmd
{
SCROLL_LEFT, SCROLL_RIGHT, SORT_BY_SLOT, SORT_BY_CLASS, SORT_BY_COST
};
ManageBackpackArtifacts() = default;
ManageBackpackArtifacts(const ObjectInstanceID & artHolder, const ManageCmd & cmd)
: artHolder(artHolder)
, cmd(cmd)
{
}
ObjectInstanceID artHolder;
ManageCmd cmd;
void visitTyped(ICPackVisitor & visitor) override;
template <typename Handler> void serialize(Handler & h)
{
h & static_cast<CPackForServer&>(*this);
h & artHolder;
h & cmd;
}
};
struct DLL_LINKAGE AssembleArtifacts : public CPackForServer
{
AssembleArtifacts() = default;

View File

@ -49,6 +49,7 @@ void registerTypesServerPacks(Serializer &s)
s.template registerType<CPackForServer, BulkSmartSplitStack>();
s.template registerType<CPackForServer, BulkMoveArmy>();
s.template registerType<CPackForServer, BulkExchangeArtifacts>();
s.template registerType < CPackForServer, ManageBackpackArtifacts>();
s.template registerType<CPackForServer, EraseArtifactByClient>();
s.template registerType<CPackForServer, GamePause>();
}

View File

@ -218,6 +218,15 @@ public:
load( data[i]);
}
template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0>
void load(std::deque<T> & data)
{
ui32 length = readAndCheckLength();
data.resize(length);
for(ui32 i = 0; i < length; i++)
load(data[i]);
}
template < typename T, typename std::enable_if_t < std::is_pointer_v<T>, int > = 0 >
void load(T &data)
{

View File

@ -276,6 +276,14 @@ public:
for(ui32 i=0;i<length;i++)
save(data[i]);
}
template <typename T, typename std::enable_if_t < !std::is_same_v<T, bool >, int > = 0>
void save(const std::deque<T> & data)
{
ui32 length = (ui32)data.size();
*this & length;
for(ui32 i = 0; i < length; i++)
save(data[i]);
}
template <typename T, size_t N>
void save(const std::array<T, N> &data)
{

View File

@ -2690,7 +2690,7 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
// With the amount of changes done to the function, it's more like transferArtifacts.
// Function moves artifact from src to dst. If dst is not a backpack and is already occupied, old dst art goes to backpack and is replaced.
bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst)
bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocation & src, const ArtifactLocation & dst)
{
const auto srcArtSet = getArtSet(src);
const auto dstArtSet = getArtSet(dst);
@ -2733,7 +2733,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
if(src.slot == dstSlot && src.artHolder == dst.artHolder)
COMPLAIN_RET("Won't move artifact: Dest same as source!");
BulkMoveArtifacts ma(src.artHolder, dst.artHolder, false);
BulkMoveArtifacts ma(player, src.artHolder, dst.artHolder, false);
ma.srcCreature = src.creature;
ma.dstCreature = dst.creature;
@ -2756,7 +2756,7 @@ bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLoca
return true;
}
bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack)
bool CGameHandler::bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack)
{
// Make sure exchange is even possible between the two heroes.
if(!isAllowedExchange(srcId, dstId))
@ -2767,7 +2767,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID ds
if((!psrcSet) || (!pdstSet))
COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID");
BulkMoveArtifacts ma(srcId, dstId, swap);
BulkMoveArtifacts ma(player, srcId, dstId, swap);
auto & slotsSrcDst = ma.artsPack0;
auto & slotsDstSrc = ma.artsPack1;
@ -2857,6 +2857,25 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID ds
return true;
}
bool CGameHandler::scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left)
{
auto artSet = getArtSet(heroID);
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "scrollBackpackArtifacts: wrong hero's ID");
BulkMoveArtifacts bma(player, heroID, heroID, false);
const auto backpackEnd = ArtifactPosition(ArtifactPosition::BACKPACK_START + artSet->artifactsInBackpack.size() - 1);
if(backpackEnd > ArtifactPosition::BACKPACK_START)
{
if(left)
bma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(backpackEnd, ArtifactPosition::BACKPACK_START));
else
bma.artsPack0.push_back(BulkMoveArtifacts::LinkedSlots(ArtifactPosition::BACKPACK_START, backpackEnd));
sendAndApply(&bma);
}
return true;
}
/**
* Assembles or disassembles a combination artifact.
* @param heroID ID of hero holding the artifact(s).

View File

@ -128,8 +128,9 @@ public:
bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos = ArtifactPosition::FIRST_AVAILABLE) override;
bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override;
void removeArtifact(const ArtifactLocation &al) override;
bool moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst) override;
bool bulkMoveArtifacts(ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack);
bool moveArtifact(const PlayerColor & player, const ArtifactLocation & src, const ArtifactLocation & dst) override;
bool bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack);
bool scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left);
bool eraseArtifactByClient(const ArtifactLocation & al);
void synchronizeArtifactHandlerLists();

View File

@ -136,7 +136,7 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
{
if(gh.getHero(pack.src.artHolder))
gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally
result = gh.moveArtifact(pack.src, pack.dst);
result = gh.moveArtifact(pack.player, pack.src, pack.dst);
}
void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
@ -145,7 +145,28 @@ void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & p
gh.throwIfWrongOwner(&pack, pack.srcHero);
if(pack.swap)
gh.throwIfWrongOwner(&pack, pack.dstHero);
result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack);
result = gh.bulkMoveArtifacts(pack.player, pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack);
}
void ApplyGhNetPackVisitor::visitManageBackpackArtifacts(ManageBackpackArtifacts & pack)
{
if(gh.getPlayerRelations(pack.player, gh.getOwner(pack.artHolder)) != PlayerRelations::ENEMIES)
{
if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SCROLL_LEFT)
result = gh.scrollBackpackArtifacts(pack.player, pack.artHolder, true);
else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SCROLL_RIGHT)
result = gh.scrollBackpackArtifacts(pack.player, pack.artHolder, false);
else
{
gh.throwIfWrongOwner(&pack, pack.artHolder);
if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_CLASS)
result = true;
else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_COST)
result = true;
else if(pack.cmd == ManageBackpackArtifacts::ManageCmd::SORT_BY_SLOT)
result = true;
}
}
}
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)

View File

@ -46,6 +46,7 @@ public:
void visitGarrisonHeroSwap(GarrisonHeroSwap & pack) override;
void visitExchangeArtifacts(ExchangeArtifacts & pack) override;
void visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) override;
void visitManageBackpackArtifacts(ManageBackpackArtifacts & pack) override;
void visitAssembleArtifacts(AssembleArtifacts & pack) override;
void visitEraseArtifactByClient(EraseArtifactByClient & pack) override;
void visitBuyArtifact(BuyArtifact & pack) override;

View File

@ -128,6 +128,9 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const
if(auto arts = dynamic_ptr_cast<BulkExchangeArtifacts>(pack))
return !vstd::contains(ourIds, arts->srcHero) || !vstd::contains(ourIds, arts->dstHero);
if(auto arts = dynamic_ptr_cast<ManageBackpackArtifacts>(pack))
return !vstd::contains(ourIds, arts->artHolder);
if(auto art = dynamic_ptr_cast<EraseArtifactByClient>(pack))
{
if(auto id = art->al.artHolder)
@ -203,6 +206,9 @@ bool OpenWindowQuery::blocksPack(const CPack *pack) const
if(dynamic_ptr_cast<BulkExchangeArtifacts>(pack) != nullptr)
return false;
if(dynamic_ptr_cast<ManageBackpackArtifacts>(pack) != nullptr)
return false;
if(dynamic_ptr_cast<AssembleArtifacts>(pack))
return false;

View File

@ -70,7 +70,7 @@ public:
bool giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact * artType, ArtifactPosition pos) override {return false;}
bool putArtifact(const ArtifactLocation & al, const CArtifactInstance * art, std::optional<bool> askAssemble) override {return false;}
void removeArtifact(const ArtifactLocation &al) override {}
bool moveArtifact(const ArtifactLocation &al1, const ArtifactLocation &al2) override {return false;}
bool moveArtifact(const PlayerColor & player, const ArtifactLocation & al1, const ArtifactLocation & al2) override {return false;}
void heroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {}
void stopHeroVisitCastle(const CGTownInstance * obj, const CGHeroInstance * hero) override {}