mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-22 22:13:35 +02:00
Switching costume
This commit is contained in:
parent
25dea7e364
commit
ce9d2d8ab8
@ -195,8 +195,6 @@ void CCallback::scrollBackpackArtifacts(ObjectInstanceID hero, bool left)
|
|||||||
|
|
||||||
void CCallback::manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume)
|
void CCallback::manageHeroCostume(ObjectInstanceID hero, size_t costumeIndex, bool saveCostume)
|
||||||
{
|
{
|
||||||
assert(costumeIndex < GameConstants::HERO_COSTUMES_ARTIFACTS);
|
|
||||||
|
|
||||||
ManageEquippedArtifacts mea(hero, costumeIndex, saveCostume);
|
ManageEquippedArtifacts mea(hero, costumeIndex, saveCostume);
|
||||||
sendRequest(&mea);
|
sendRequest(&mea);
|
||||||
}
|
}
|
||||||
|
@ -314,12 +314,20 @@ CKeyShortcut::CKeyShortcut(EShortcut key)
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CKeyShortcut::CKeyShortcut(const EShortcut & key, const KeyPressedFunctor & keyPressedCallback)
|
||||||
|
: CKeyShortcut(key)
|
||||||
|
{
|
||||||
|
this->keyPressedCallback = keyPressedCallback;
|
||||||
|
}
|
||||||
|
|
||||||
void CKeyShortcut::keyPressed(EShortcut key)
|
void CKeyShortcut::keyPressed(EShortcut key)
|
||||||
{
|
{
|
||||||
if( assignedKey == key && assignedKey != EShortcut::NONE && !shortcutPressed)
|
if( assignedKey == key && assignedKey != EShortcut::NONE && !shortcutPressed)
|
||||||
{
|
{
|
||||||
shortcutPressed = true;
|
shortcutPressed = true;
|
||||||
clickPressed(GH.getCursorPosition());
|
clickPressed(GH.getCursorPosition());
|
||||||
|
if(keyPressedCallback)
|
||||||
|
keyPressedCallback();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -133,14 +133,19 @@ public:
|
|||||||
/// Classes wanting use it should have it as one of their base classes
|
/// Classes wanting use it should have it as one of their base classes
|
||||||
class CKeyShortcut : public virtual CIntObject
|
class CKeyShortcut : public virtual CIntObject
|
||||||
{
|
{
|
||||||
bool shortcutPressed;
|
|
||||||
public:
|
public:
|
||||||
|
using KeyPressedFunctor = std::function<void()>;
|
||||||
|
|
||||||
EShortcut assignedKey;
|
EShortcut assignedKey;
|
||||||
CKeyShortcut();
|
CKeyShortcut();
|
||||||
CKeyShortcut(EShortcut key);
|
CKeyShortcut(EShortcut key);
|
||||||
|
CKeyShortcut(const EShortcut & key, const KeyPressedFunctor & keyPressedCallback);
|
||||||
void keyPressed(EShortcut key) override;
|
void keyPressed(EShortcut key) override;
|
||||||
void keyReleased(EShortcut key) override;
|
void keyReleased(EShortcut key) override;
|
||||||
|
|
||||||
|
private:
|
||||||
|
bool shortcutPressed;
|
||||||
|
KeyPressedFunctor keyPressedCallback;
|
||||||
};
|
};
|
||||||
|
|
||||||
class WindowBase : public CIntObject
|
class WindowBase : public CIntObject
|
||||||
|
@ -18,7 +18,7 @@
|
|||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
#include "../../lib/networkPacks/ArtifactLocation.h"
|
#include "../../lib/networkPacks/ArtifactLocation.h"
|
||||||
|
|
||||||
CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position, bool costumesEnabled)
|
CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position)
|
||||||
{
|
{
|
||||||
init(
|
init(
|
||||||
std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2),
|
std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2),
|
||||||
@ -26,21 +26,6 @@ CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position, bool costumes
|
|||||||
position,
|
position,
|
||||||
std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
|
std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
|
||||||
addGestureCallback(std::bind(&CArtifactsOfHeroBase::gestureArtPlace, this, _1, _2));
|
addGestureCallback(std::bind(&CArtifactsOfHeroBase::gestureArtPlace, this, _1, _2));
|
||||||
|
|
||||||
if(costumesEnabled)
|
|
||||||
{
|
|
||||||
size_t costumeIndex = 0;
|
|
||||||
for(const auto & hotkey : hotkeys)
|
|
||||||
{
|
|
||||||
auto keyProc = costumesSwitchers.emplace_back(std::make_shared<CKeyShortcutWrapper>(hotkey,
|
|
||||||
[this, hotkey, costumeIndex]()
|
|
||||||
{
|
|
||||||
CArtifactsOfHeroMain::onCostumeSelect(costumeIndex);
|
|
||||||
}));
|
|
||||||
keyProc->addUsedEvents(AEventsReceiver::KEYBOARD);
|
|
||||||
costumeIndex++;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CArtifactsOfHeroMain::~CArtifactsOfHeroMain()
|
CArtifactsOfHeroMain::~CArtifactsOfHeroMain()
|
||||||
@ -48,19 +33,17 @@ CArtifactsOfHeroMain::~CArtifactsOfHeroMain()
|
|||||||
CArtifactsOfHeroBase::putBackPickedArtifact();
|
CArtifactsOfHeroBase::putBackPickedArtifact();
|
||||||
}
|
}
|
||||||
|
|
||||||
void CArtifactsOfHeroMain::onCostumeSelect(const size_t costumeIndex)
|
void CArtifactsOfHeroMain::enableArtifactsCostumeSwitcher()
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->manageHeroCostume(getHero()->id, costumeIndex, GH.isKeyboardCtrlDown());
|
size_t costumeIdx = 0;
|
||||||
}
|
for(const auto & hotkey : costumesSwitcherHotkeys)
|
||||||
|
{
|
||||||
CArtifactsOfHeroMain::CKeyShortcutWrapper::CKeyShortcutWrapper(const EShortcut & key, const KeyPressedFunctor & onCostumeSelect)
|
auto keyProc = costumesSwitcherProcessors.emplace_back(std::make_shared<CKeyShortcut>(hotkey,
|
||||||
: CKeyShortcut(key)
|
[this, costumeIdx]()
|
||||||
, onCostumeSelect(onCostumeSelect)
|
{
|
||||||
{
|
LOCPLINT->cb->manageHeroCostume(getHero()->id, costumeIdx, GH.isKeyboardCtrlDown());
|
||||||
}
|
}));
|
||||||
|
keyProc->addUsedEvents(AEventsReceiver::KEYBOARD);
|
||||||
void CArtifactsOfHeroMain::CKeyShortcutWrapper::clickPressed(const Point & cursorPosition)
|
costumeIdx++;
|
||||||
{
|
}
|
||||||
if(onCostumeSelect)
|
|
||||||
onCostumeSelect();
|
|
||||||
}
|
}
|
||||||
|
@ -16,24 +16,12 @@
|
|||||||
class CArtifactsOfHeroMain : public CArtifactsOfHeroBase
|
class CArtifactsOfHeroMain : public CArtifactsOfHeroBase
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CArtifactsOfHeroMain(const Point & position, bool costumesEnabled = false);
|
CArtifactsOfHeroMain(const Point & position);
|
||||||
~CArtifactsOfHeroMain() override;
|
~CArtifactsOfHeroMain() override;
|
||||||
|
void enableArtifactsCostumeSwitcher();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
// TODO may be removed if CKeyShortcut supports callbacks
|
const std::vector<EShortcut> costumesSwitcherHotkeys =
|
||||||
class CKeyShortcutWrapper : public CKeyShortcut
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
using KeyPressedFunctor = std::function<void()>;
|
|
||||||
|
|
||||||
CKeyShortcutWrapper(const EShortcut & key, const KeyPressedFunctor & onCostumeSelect);
|
|
||||||
void clickPressed(const Point & cursorPosition) override;
|
|
||||||
|
|
||||||
private:
|
|
||||||
KeyPressedFunctor onCostumeSelect;
|
|
||||||
};
|
|
||||||
|
|
||||||
const std::array<EShortcut, GameConstants::HERO_COSTUMES_ARTIFACTS> hotkeys =
|
|
||||||
{
|
{
|
||||||
EShortcut::HERO_COSTUME_0,
|
EShortcut::HERO_COSTUME_0,
|
||||||
EShortcut::HERO_COSTUME_1,
|
EShortcut::HERO_COSTUME_1,
|
||||||
@ -46,7 +34,5 @@ private:
|
|||||||
EShortcut::HERO_COSTUME_8,
|
EShortcut::HERO_COSTUME_8,
|
||||||
EShortcut::HERO_COSTUME_9
|
EShortcut::HERO_COSTUME_9
|
||||||
};
|
};
|
||||||
std::vector<std::shared_ptr<CKeyShortcutWrapper>> costumesSwitchers;
|
std::vector<std::shared_ptr<CKeyShortcut>> costumesSwitcherProcessors;
|
||||||
|
|
||||||
void onCostumeSelect(const size_t costumeIndex);
|
|
||||||
};
|
};
|
||||||
|
@ -218,9 +218,10 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
|
|||||||
}
|
}
|
||||||
if(!arts)
|
if(!arts)
|
||||||
{
|
{
|
||||||
arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8), true);
|
arts = std::make_shared<CArtifactsOfHeroMain>(Point(-65, -8));
|
||||||
arts->setHero(curHero);
|
arts->setHero(curHero);
|
||||||
addSetAndCallbacks(arts);
|
addSetAndCallbacks(arts);
|
||||||
|
enableArtifactsCostumeSwitcher();
|
||||||
}
|
}
|
||||||
|
|
||||||
int serial = LOCPLINT->cb->getHeroSerial(curHero, false);
|
int serial = LOCPLINT->cb->getHeroSerial(curHero, false);
|
||||||
|
@ -343,6 +343,20 @@ void CWindowWithArtifacts::deactivate()
|
|||||||
CWindowObject::deactivate();
|
CWindowObject::deactivate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CWindowWithArtifacts::enableArtifactsCostumeSwitcher()
|
||||||
|
{
|
||||||
|
for(auto artSet : artSets)
|
||||||
|
std::visit(
|
||||||
|
[](auto artSetWeak)
|
||||||
|
{
|
||||||
|
if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroMain>>)
|
||||||
|
{
|
||||||
|
const auto artSetPtr = artSetWeak.lock();
|
||||||
|
artSetPtr->enableArtifactsCostumeSwitcher();
|
||||||
|
}
|
||||||
|
}, artSet);
|
||||||
|
}
|
||||||
|
|
||||||
void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
|
void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
|
||||||
{
|
{
|
||||||
update();
|
update();
|
||||||
|
@ -42,6 +42,7 @@ public:
|
|||||||
void gestureArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
|
void gestureArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition);
|
||||||
void activate() override;
|
void activate() override;
|
||||||
void deactivate() override;
|
void deactivate() override;
|
||||||
|
void enableArtifactsCostumeSwitcher();
|
||||||
|
|
||||||
virtual void artifactRemoved(const ArtifactLocation & artLoc);
|
virtual void artifactRemoved(const ArtifactLocation & artLoc);
|
||||||
virtual void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw);
|
virtual void artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw);
|
||||||
|
@ -52,7 +52,7 @@ DLL_LINKAGE const std::vector<ArtifactPosition> & ArtifactUtils::unmovableSlots(
|
|||||||
return positions;
|
return positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
DLL_LINKAGE const std::vector<ArtifactPosition> & ArtifactUtils::constituentWornSlots()
|
DLL_LINKAGE const std::vector<ArtifactPosition> & ArtifactUtils::commonWornSlots()
|
||||||
{
|
{
|
||||||
static const std::vector<ArtifactPosition> positions =
|
static const std::vector<ArtifactPosition> positions =
|
||||||
{
|
{
|
||||||
|
@ -30,7 +30,7 @@ namespace ArtifactUtils
|
|||||||
DLL_LINKAGE ArtifactPosition getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid);
|
DLL_LINKAGE ArtifactPosition getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid);
|
||||||
// TODO: Make this constexpr when the toolset is upgraded
|
// TODO: Make this constexpr when the toolset is upgraded
|
||||||
DLL_LINKAGE const std::vector<ArtifactPosition> & unmovableSlots();
|
DLL_LINKAGE const std::vector<ArtifactPosition> & unmovableSlots();
|
||||||
DLL_LINKAGE const std::vector<ArtifactPosition> & constituentWornSlots();
|
DLL_LINKAGE const std::vector<ArtifactPosition> & commonWornSlots();
|
||||||
DLL_LINKAGE const std::vector<ArtifactPosition> & allWornSlots();
|
DLL_LINKAGE const std::vector<ArtifactPosition> & allWornSlots();
|
||||||
DLL_LINKAGE const std::vector<ArtifactPosition> & commanderSlots();
|
DLL_LINKAGE const std::vector<ArtifactPosition> & commanderSlots();
|
||||||
DLL_LINKAGE bool isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot);
|
DLL_LINKAGE bool isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot);
|
||||||
|
@ -1086,6 +1086,14 @@ CArtifactFittingSet::CArtifactFittingSet(ArtBearer::ArtBearer Bearer):
|
|||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CArtifactFittingSet::CArtifactFittingSet(const CArtifactSet & artSet)
|
||||||
|
: CArtifactFittingSet(artSet.bearerType())
|
||||||
|
{
|
||||||
|
artifactsWorn = artSet.artifactsWorn;
|
||||||
|
artifactsInBackpack = artSet.artifactsInBackpack;
|
||||||
|
artifactsTransitionPos = artSet.artifactsTransitionPos;
|
||||||
|
}
|
||||||
|
|
||||||
ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const
|
ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const
|
||||||
{
|
{
|
||||||
return this->Bearer;
|
return this->Bearer;
|
||||||
|
@ -249,6 +249,7 @@ class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet
|
|||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CArtifactFittingSet(ArtBearer::ArtBearer Bearer);
|
CArtifactFittingSet(ArtBearer::ArtBearer Bearer);
|
||||||
|
CArtifactFittingSet(const CArtifactSet & artSet);
|
||||||
ArtBearer::ArtBearer bearerType() const override;
|
ArtBearer::ArtBearer bearerType() const override;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
|
@ -1075,7 +1075,7 @@ void ChangeObjectVisitors::applyGs(CGameState * gs) const
|
|||||||
void ChangeArtifactsCostume::applyGs(CGameState * gs) const
|
void ChangeArtifactsCostume::applyGs(CGameState * gs) const
|
||||||
{
|
{
|
||||||
auto & allCostumes = gs->getPlayerState(player)->costumesArtifacts;
|
auto & allCostumes = gs->getPlayerState(player)->costumesArtifacts;
|
||||||
if(auto & costume = allCostumes.find(costumeIdx); costume != allCostumes.end())
|
if(const auto & costume = allCostumes.find(costumeIdx); costume != allCostumes.end())
|
||||||
costume->second = costumeSet;
|
costume->second = costumeSet;
|
||||||
else
|
else
|
||||||
allCostumes.emplace(costumeIdx, costumeSet);
|
allCostumes.emplace(costumeIdx, costumeSet);
|
||||||
@ -1802,69 +1802,47 @@ void MoveArtifact::applyGs(CGameState * gs)
|
|||||||
|
|
||||||
void BulkMoveArtifacts::applyGs(CGameState * gs)
|
void BulkMoveArtifacts::applyGs(CGameState * gs)
|
||||||
{
|
{
|
||||||
enum class EBulkArtsOp
|
const auto bulkArtsRemove = [](std::vector<LinkedSlots> & artsPack, CArtifactSet & artSet)
|
||||||
{
|
{
|
||||||
BULK_MOVE,
|
std::vector<ArtifactPosition> packToRemove;
|
||||||
BULK_REMOVE,
|
for(const auto & slotsPair : artsPack)
|
||||||
BULK_PUT
|
packToRemove.push_back(slotsPair.srcPos);
|
||||||
|
std::sort(packToRemove.begin(), packToRemove.end(), [](const ArtifactPosition & slot0, const ArtifactPosition & slot1) -> bool
|
||||||
|
{
|
||||||
|
return slot0.num > slot1.num;
|
||||||
|
});
|
||||||
|
|
||||||
|
for(const auto & slot : packToRemove)
|
||||||
|
{
|
||||||
|
auto * art = artSet.getArt(slot);
|
||||||
|
assert(art);
|
||||||
|
art->removeFrom(artSet, slot);
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto bulkArtsOperation = [this, gs](std::vector<LinkedSlots> & artsPack,
|
const auto bulkArtsPut = [](std::vector<LinkedSlots> & artsPack, CArtifactSet & initArtSet, CArtifactSet & dstArtSet)
|
||||||
CArtifactSet & artSet, EBulkArtsOp operation) -> void
|
|
||||||
{
|
{
|
||||||
int numBackpackArtifactsMoved = 0;
|
for(const auto & slotsPair : artsPack)
|
||||||
for(auto & slot : artsPack)
|
|
||||||
{
|
{
|
||||||
// When an object gets removed from the backpack, the backpack shrinks
|
auto * art = initArtSet.getArt(slotsPair.srcPos);
|
||||||
// so all the following indices will be affected. Thus, we need to update
|
|
||||||
// the subsequent artifact slots to account for that
|
|
||||||
auto srcPos = slot.srcPos;
|
|
||||||
if(ArtifactUtils::isSlotBackpack(srcPos) && (operation != EBulkArtsOp::BULK_PUT))
|
|
||||||
{
|
|
||||||
srcPos = ArtifactPosition(srcPos.num - numBackpackArtifactsMoved);
|
|
||||||
}
|
|
||||||
auto * art = artSet.getArt(srcPos);
|
|
||||||
assert(art);
|
assert(art);
|
||||||
switch(operation)
|
art->putAt(dstArtSet, slotsPair.dstPos);
|
||||||
{
|
|
||||||
case EBulkArtsOp::BULK_MOVE:
|
|
||||||
art->move(artSet, srcPos, *gs->getArtSet(ArtifactLocation(dstArtHolder, dstCreature)), slot.dstPos);
|
|
||||||
break;
|
|
||||||
case EBulkArtsOp::BULK_REMOVE:
|
|
||||||
art->removeFrom(artSet, srcPos);
|
|
||||||
break;
|
|
||||||
case EBulkArtsOp::BULK_PUT:
|
|
||||||
art->putAt(*gs->getArtSet(ArtifactLocation(srcArtHolder, srcCreature)), slot.dstPos);
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(srcPos >= ArtifactPosition::BACKPACK_START)
|
|
||||||
{
|
|
||||||
numBackpackArtifactsMoved++;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto * leftSet = gs->getArtSet(ArtifactLocation(srcArtHolder, srcCreature));
|
auto * leftSet = gs->getArtSet(ArtifactLocation(srcArtHolder, srcCreature));
|
||||||
if(swap)
|
assert(leftSet);
|
||||||
{
|
|
||||||
// Swap
|
|
||||||
auto * rightSet = gs->getArtSet(ArtifactLocation(dstArtHolder, dstCreature));
|
auto * rightSet = gs->getArtSet(ArtifactLocation(dstArtHolder, dstCreature));
|
||||||
CArtifactFittingSet artFittingSet(leftSet->bearerType());
|
assert(rightSet);
|
||||||
|
CArtifactFittingSet artInitialSetLeft(*leftSet);
|
||||||
artFittingSet.artifactsWorn = rightSet->artifactsWorn;
|
bulkArtsRemove(artsPack0, *leftSet);
|
||||||
artFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack;
|
if(!artsPack1.empty())
|
||||||
|
|
||||||
bulkArtsOperation(artsPack1, *rightSet, EBulkArtsOp::BULK_REMOVE);
|
|
||||||
bulkArtsOperation(artsPack0, *leftSet, EBulkArtsOp::BULK_MOVE);
|
|
||||||
bulkArtsOperation(artsPack1, artFittingSet, EBulkArtsOp::BULK_PUT);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
{
|
||||||
bulkArtsOperation(artsPack0, *leftSet, EBulkArtsOp::BULK_MOVE);
|
CArtifactFittingSet artInitialSetRight(*rightSet);
|
||||||
|
bulkArtsRemove(artsPack1, *rightSet);
|
||||||
|
bulkArtsPut(artsPack1, artInitialSetRight, *leftSet);
|
||||||
}
|
}
|
||||||
|
bulkArtsPut(artsPack0, artInitialSetLeft, *rightSet);
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssembledArtifact::applyGs(CGameState *gs)
|
void AssembledArtifact::applyGs(CGameState *gs)
|
||||||
|
@ -1291,8 +1291,8 @@ struct DLL_LINKAGE ChangeObjectVisitors : public CPackForClient
|
|||||||
struct DLL_LINKAGE ChangeArtifactsCostume : public CPackForClient
|
struct DLL_LINKAGE ChangeArtifactsCostume : public CPackForClient
|
||||||
{
|
{
|
||||||
std::map<ArtifactPosition, ArtifactID> costumeSet;
|
std::map<ArtifactPosition, ArtifactID> costumeSet;
|
||||||
size_t costumeIdx;
|
size_t costumeIdx = 0;
|
||||||
const PlayerColor player;
|
const PlayerColor player = PlayerColor::NEUTRAL;
|
||||||
|
|
||||||
void applyGs(CGameState * gs) const;
|
void applyGs(CGameState * gs) const;
|
||||||
void visitTyped(ICPackVisitor & visitor) override;
|
void visitTyped(ICPackVisitor & visitor) override;
|
||||||
|
@ -2896,13 +2896,11 @@ bool CGameHandler::saveArtifactsCostume(const PlayerColor & player, const Object
|
|||||||
{
|
{
|
||||||
auto artSet = getArtSet(heroID);
|
auto artSet = getArtSet(heroID);
|
||||||
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "saveArtifactsCostume: wrong hero's ID");
|
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "saveArtifactsCostume: wrong hero's ID");
|
||||||
COMPLAIN_RET_FALSE_IF(costumeIdx >= GameConstants::HERO_COSTUMES_ARTIFACTS, "saveArtifactsCostume: wrong costume index");
|
|
||||||
|
|
||||||
ChangeArtifactsCostume costume(player, costumeIdx);
|
ChangeArtifactsCostume costume(player, costumeIdx);
|
||||||
for(const auto & slot : ArtifactUtils::constituentWornSlots())
|
for(const auto & slot : ArtifactUtils::commonWornSlots())
|
||||||
{
|
{
|
||||||
if(const auto & slotInfo = artSet->getSlot(slot))
|
if(const auto slotInfo = artSet->getSlot(slot); slotInfo != nullptr && !slotInfo->locked)
|
||||||
if(!slotInfo->locked)
|
|
||||||
costume.costumeSet.emplace(slot, slotInfo->getArt()->getTypeId());
|
costume.costumeSet.emplace(slot, slotInfo->getArt()->getTypeId());
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -2910,6 +2908,62 @@ bool CGameHandler::saveArtifactsCostume(const PlayerColor & player, const Object
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool CGameHandler::switchArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx)
|
||||||
|
{
|
||||||
|
const auto artSet = getArtSet(heroID);
|
||||||
|
COMPLAIN_RET_FALSE_IF(artSet == nullptr, "switchArtifactsCostume: wrong hero's ID");
|
||||||
|
const auto playerState = getPlayerState(player);
|
||||||
|
COMPLAIN_RET_FALSE_IF(playerState == nullptr, "switchArtifactsCostume: wrong player");
|
||||||
|
|
||||||
|
if(auto costume = playerState->costumesArtifacts.find(costumeIdx); costume != playerState->costumesArtifacts.end())
|
||||||
|
{
|
||||||
|
CArtifactFittingSet artFittingSet(*artSet);
|
||||||
|
BulkMoveArtifacts bma(player, heroID, heroID, false);
|
||||||
|
auto costumeArtMap = costume->second;
|
||||||
|
auto estimateBackpackSize = artSet->artifactsInBackpack.size();
|
||||||
|
|
||||||
|
// First, find those artifacts that are already in place
|
||||||
|
for(const auto & slot : ArtifactUtils::commonWornSlots())
|
||||||
|
{
|
||||||
|
if(const auto * slotInfo = artFittingSet.getSlot(slot); slotInfo != nullptr && !slotInfo->locked)
|
||||||
|
if(const auto artPos = costumeArtMap.find(slot); artPos != costumeArtMap.end() && artPos->second == slotInfo->getArt()->getTypeId())
|
||||||
|
{
|
||||||
|
costumeArtMap.erase(artPos);
|
||||||
|
artFittingSet.removeArtifact(slot);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Second, find the necessary artifacts for the costume
|
||||||
|
for(const auto & artPos : costumeArtMap)
|
||||||
|
{
|
||||||
|
if(const auto availableArts = artFittingSet.getAllArtPositions(artPos.second, false, false, false); !availableArts.empty())
|
||||||
|
{
|
||||||
|
bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots
|
||||||
|
{
|
||||||
|
artSet->getSlotByInstance(artFittingSet.getArt(availableArts.front())),
|
||||||
|
artPos.first
|
||||||
|
});
|
||||||
|
artFittingSet.removeArtifact(availableArts.front());
|
||||||
|
if(ArtifactUtils::isSlotBackpack(availableArts.front()))
|
||||||
|
estimateBackpackSize--;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Third, put unnecessary artifacts into backpack
|
||||||
|
for(const auto & slot : ArtifactUtils::commonWornSlots())
|
||||||
|
if(artFittingSet.getArt(slot))
|
||||||
|
{
|
||||||
|
bma.artsPack0.emplace_back(BulkMoveArtifacts::LinkedSlots{slot, ArtifactPosition::BACKPACK_START});
|
||||||
|
estimateBackpackSize++;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto backpackCap = VLC->settings()->getInteger(EGameSettings::HEROES_BACKPACK_CAP);
|
||||||
|
if((backpackCap < 0 || estimateBackpackSize <= backpackCap) && !bma.artsPack0.empty())
|
||||||
|
sendAndApply(&bma);
|
||||||
|
}
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Assembles or disassembles a combination artifact.
|
* Assembles or disassembles a combination artifact.
|
||||||
* @param heroID ID of hero holding the artifact(s).
|
* @param heroID ID of hero holding the artifact(s).
|
||||||
|
@ -131,6 +131,7 @@ public:
|
|||||||
bool bulkMoveArtifacts(const PlayerColor & player, ObjectInstanceID srcId, ObjectInstanceID dstId, bool swap, bool equipped, bool backpack);
|
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 scrollBackpackArtifacts(const PlayerColor & player, const ObjectInstanceID heroID, bool left);
|
||||||
bool saveArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx);
|
bool saveArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx);
|
||||||
|
bool switchArtifactsCostume(const PlayerColor & player, const ObjectInstanceID heroID, size_t costumeIdx);
|
||||||
bool eraseArtifactByClient(const ArtifactLocation & al);
|
bool eraseArtifactByClient(const ArtifactLocation & al);
|
||||||
void synchronizeArtifactHandlerLists();
|
void synchronizeArtifactHandlerLists();
|
||||||
|
|
||||||
|
@ -183,8 +183,9 @@ void ApplyGhNetPackVisitor::visitManageEquippedArtifacts(ManageEquippedArtifacts
|
|||||||
{
|
{
|
||||||
gh.throwIfWrongOwner(&pack, pack.artHolder);
|
gh.throwIfWrongOwner(&pack, pack.artHolder);
|
||||||
if(pack.saveCostume)
|
if(pack.saveCostume)
|
||||||
gh.saveArtifactsCostume(pack.player, pack.artHolder, pack.costumeIdx);
|
result = gh.saveArtifactsCostume(pack.player, pack.artHolder, pack.costumeIdx);
|
||||||
result = true;
|
else
|
||||||
|
result = gh.switchArtifactsCostume(pack.player, pack.artHolder, pack.costumeIdx);
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
|
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
|
||||||
|
Loading…
Reference in New Issue
Block a user