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

ArtifactPosition::TRANSITION_POS now is simple ArtSlotInfo

This commit is contained in:
SoundSSGood
2024-04-30 12:39:20 +03:00
parent 721b15d9de
commit 7abfa7b42a
15 changed files with 120 additions and 142 deletions

View File

@@ -126,7 +126,7 @@ size_t CArtifactsOfHeroBackpack::calcRows(size_t slots)
CArtifactsOfHeroQuickBackpack::CArtifactsOfHeroQuickBackpack(const ArtifactPosition filterBySlot) CArtifactsOfHeroQuickBackpack::CArtifactsOfHeroQuickBackpack(const ArtifactPosition filterBySlot)
: CArtifactsOfHeroBackpack(0, 0) : CArtifactsOfHeroBackpack(0, 0)
{ {
assert(filterBySlot != ArtifactPosition::FIRST_AVAILABLE); assert(ArtifactUtils::checkIfSlotValid(*getHero(), filterBySlot));
if(!ArtifactUtils::isSlotEquipment(filterBySlot)) if(!ArtifactUtils::isSlotEquipment(filterBySlot))
return; return;

View File

@@ -32,9 +32,9 @@ CArtifactsOfHeroBase::CArtifactsOfHeroBase()
void CArtifactsOfHeroBase::putBackPickedArtifact() void CArtifactsOfHeroBase::putBackPickedArtifact()
{ {
// Artifact located in artifactsTransitionPos should be returned // Artifact located in artifactsTransitionPos should be returned
if(getPickedArtifact()) if(const auto art = getPickedArtifact())
{ {
auto slot = ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->getTypeId()); auto slot = ArtifactUtils::getArtAnyPosition(curHero, art->getTypeId());
if(slot == ArtifactPosition::PRE_FIRST) if(slot == ArtifactPosition::PRE_FIRST)
{ {
LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS)); LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
@@ -196,10 +196,10 @@ void CArtifactsOfHeroBase::updateSlot(const ArtifactPosition & slot)
const CArtifactInstance * CArtifactsOfHeroBase::getPickedArtifact() const CArtifactInstance * CArtifactsOfHeroBase::getPickedArtifact()
{ {
// Returns only the picked up artifact. Not just highlighted like in the trading window. // Returns only the picked up artifact. Not just highlighted like in the trading window.
if(!curHero || curHero->artifactsTransitionPos.empty()) if(curHero)
return nullptr;
else
return curHero->getArt(ArtifactPosition::TRANSITION_POS); return curHero->getArt(ArtifactPosition::TRANSITION_POS);
else
return nullptr;
} }
void CArtifactsOfHeroBase::addGestureCallback(CArtPlace::ClickFunctor callback) void CArtifactsOfHeroBase::addGestureCallback(CArtPlace::ClickFunctor callback)

View File

@@ -222,7 +222,8 @@ void CAltarArtifacts::onSlotClickPressed(const std::shared_ptr<CTradeableItem> &
assert(tradeSlotsMap.at(altarSlot)); assert(tradeSlotsMap.at(altarSlot));
const auto slot = altarArtifacts->getSlotByInstance(tradeSlotsMap.at(altarSlot)); const auto slot = altarArtifacts->getSlotByInstance(tradeSlotsMap.at(altarSlot));
assert(slot != ArtifactPosition::PRE_FIRST); assert(slot != ArtifactPosition::PRE_FIRST);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot), ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS)); LOCPLINT->cb->swapArtifacts(ArtifactLocation(altarId, slot),
ArtifactLocation(hero->id, GH.isKeyboardCtrlDown() ? ArtifactPosition::FIRST_AVAILABLE : ArtifactPosition::TRANSITION_POS));
tradeSlotsMap.erase(altarSlot); tradeSlotsMap.erase(altarSlot);
} }
} }

View File

@@ -20,7 +20,7 @@
#include "render/Canvas.h" #include "render/Canvas.h"
#include "CPlayerInterface.h" #include "CPlayerInterface.h"
CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<CArtifactsOfHeroPtr> & artsSets) CHeroBackpackWindow::CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<ArtifactsOfHeroVar> & artsSets)
: CWindowWithArtifacts(&artsSets) : CWindowWithArtifacts(&artsSets)
{ {
OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE); OBJECT_CONSTRUCTION_CAPTURING(255 - DISPOSE);

View File

@@ -16,7 +16,7 @@ class CFilledTexture;
class CHeroBackpackWindow : public CStatusbarWindow, public CWindowWithArtifacts class CHeroBackpackWindow : public CStatusbarWindow, public CWindowWithArtifacts
{ {
public: public:
CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<CArtifactsOfHeroPtr> & artsSets); CHeroBackpackWindow(const CGHeroInstance * hero, const std::vector<ArtifactsOfHeroVar> & artsSets);
protected: protected:
std::shared_ptr<CArtifactsOfHeroBackpack> arts; std::shared_ptr<CArtifactsOfHeroBackpack> arts;

View File

@@ -548,7 +548,7 @@ std::shared_ptr<CIntObject> CKingdomInterface::createMainTab(size_t index)
switch(index) switch(index)
{ {
case 0: case 0:
return std::make_shared<CKingdHeroList>(size, [this](const CWindowWithArtifacts::CArtifactsOfHeroPtr & newHeroSet) return std::make_shared<CKingdHeroList>(size, [this](const CWindowWithArtifacts::ArtifactsOfHeroVar & newHeroSet)
{ {
addSetAndCallbacks(newHeroSet); addSetAndCallbacks(newHeroSet);
}); });

View File

@@ -334,7 +334,7 @@ private:
std::shared_ptr<CLabel> skillsLabel; std::shared_ptr<CLabel> skillsLabel;
public: public:
using CreateHeroItemFunctor = std::function<void(const CWindowWithArtifacts::CArtifactsOfHeroPtr)>; using CreateHeroItemFunctor = std::function<void(const CWindowWithArtifacts::ArtifactsOfHeroVar)>;
CKingdHeroList(size_t maxSize, const CreateHeroItemFunctor & onCreateHeroItemCallback); CKingdHeroList(size_t maxSize, const CreateHeroItemFunctor & onCreateHeroItemCallback);
void updateGarrisons() override; void updateGarrisons() override;

View File

@@ -106,8 +106,6 @@ void CMarketWindow::artifactRemoved(const ArtifactLocation & artLoc)
void CMarketWindow::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) void CMarketWindow::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw)
{ {
if(!getState().has_value())
return;
CWindowWithArtifacts::artifactMoved(srcLoc, destLoc, withRedraw); CWindowWithArtifacts::artifactMoved(srcLoc, destLoc, withRedraw);
assert(marketWidget); assert(marketWidget);
marketWidget->update(); marketWidget->update();

View File

@@ -35,18 +35,18 @@
#include "../../CCallback.h" #include "../../CCallback.h"
CWindowWithArtifacts::CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr> * artSets) CWindowWithArtifacts::CWindowWithArtifacts(const std::vector<ArtifactsOfHeroVar> * artSets)
{ {
if(artSets) if(artSets)
this->artSets.insert(this->artSets.end(), artSets->begin(), artSets->end()); this->artSets.insert(this->artSets.end(), artSets->begin(), artSets->end());
} }
void CWindowWithArtifacts::addSet(CArtifactsOfHeroPtr newArtSet) void CWindowWithArtifacts::addSet(ArtifactsOfHeroVar newArtSet)
{ {
artSets.emplace_back(newArtSet); artSets.emplace_back(newArtSet);
} }
void CWindowWithArtifacts::addSetAndCallbacks(CArtifactsOfHeroPtr newArtSet) void CWindowWithArtifacts::addSetAndCallbacks(ArtifactsOfHeroVar newArtSet)
{ {
addSet(newArtSet); addSet(newArtSet);
std::visit([this](auto artSetWeak) std::visit([this](auto artSetWeak)
@@ -65,20 +65,36 @@ void CWindowWithArtifacts::addCloseCallback(const CloseCallback & callback)
const CGHeroInstance * CWindowWithArtifacts::getHeroPickedArtifact() const CGHeroInstance * CWindowWithArtifacts::getHeroPickedArtifact()
{ {
auto res = getState(); const CGHeroInstance * hero = nullptr;
if(res.has_value())
return std::get<const CGHeroInstance*>(res.value()); for(auto artSetWeak : artSets)
else std::visit([&hero](auto artSetWeak)
return nullptr; {
if(auto artSetPtr = artSetWeak.lock())
if(const auto pickedArt = artSetPtr->getHero()->getArt(ArtifactPosition::TRANSITION_POS))
{
hero = artSetPtr->getHero();
return;
}
}, artSetWeak);
return hero;
} }
const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact() const CArtifactInstance * CWindowWithArtifacts::getPickedArtifact()
{ {
auto res = getState(); const CArtifactInstance * art = nullptr;
if(res.has_value())
return std::get<const CArtifactInstance*>(res.value()); for (auto artSetWeak : artSets)
else std::visit([&art](auto artSetWeak)
return nullptr; {
if(auto artSetPtr = artSetWeak.lock())
if(const auto pickedArt = artSetPtr->getHero()->getArt(ArtifactPosition::TRANSITION_POS))
{
art = pickedArt;
return;
}
}, artSetWeak);
return art;
} }
void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition)
@@ -151,70 +167,46 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase &
{ {
assert(artSetPtr->getHero()->getSlotByInstance(art) != ArtifactPosition::PRE_FIRST); assert(artSetPtr->getHero()->getSlotByInstance(art) != ArtifactPosition::PRE_FIRST);
if(GH.isKeyboardCmdDown()) auto srcLoc = ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot);
auto dstLoc = ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS);
if(GH.isKeyboardCtrlDown())
{ {
std::shared_ptr<CArtifactsOfHeroMain> anotherHeroEquipmentPointer = nullptr; std::shared_ptr<CArtifactsOfHeroBase> anotherArtSet = nullptr;
for(auto set : artSets) for(auto set : artSets)
{ {
if(std::holds_alternative<std::weak_ptr<CArtifactsOfHeroMain>>(set)) if(std::holds_alternative<std::weak_ptr<CArtifactsOfHeroMain>>(set))
{ {
std::shared_ptr<CArtifactsOfHeroMain> heroEquipmentPointer = std::get<std::weak_ptr<CArtifactsOfHeroMain>>(set).lock(); std::shared_ptr<CArtifactsOfHeroBase> heroEquipmentPointer = std::get<std::weak_ptr<CArtifactsOfHeroMain>>(set).lock();
if(heroEquipmentPointer->getHero()->id != artSetPtr->getHero()->id) if(heroEquipmentPointer->getHero()->id != artSetPtr->getHero()->id)
{ {
anotherHeroEquipmentPointer = heroEquipmentPointer; anotherArtSet = heroEquipmentPointer;
break; break;
} }
} }
} }
if(anotherHeroEquipmentPointer != nullptr) if(anotherArtSet != nullptr)
{ {
ArtifactPosition availablePosition = ArtifactUtils::getArtAnyPosition(anotherHeroEquipmentPointer->getHero(), art->getTypeId()); dstLoc.slot = ArtifactPosition::FIRST_AVAILABLE;
if(availablePosition != ArtifactPosition::PRE_FIRST) dstLoc.artHolder = anotherArtSet->getHero()->id;
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artSetPtr->getHero()->getSlotByInstance(art)),
ArtifactLocation(anotherHeroEquipmentPointer->getHero()->id, availablePosition));
}
} }
} }
else if(GH.isKeyboardAltDown()) else if(GH.isKeyboardAltDown())
{ {
ArtifactPosition destinationPosition = ArtifactPosition::PRE_FIRST;
if(ArtifactUtils::isSlotEquipment(artPlace.slot)) if(ArtifactUtils::isSlotEquipment(artPlace.slot))
{ dstLoc.slot = ArtifactUtils::getArtBackpackPosition(artSetPtr->getHero(), art->getTypeId());
ArtifactPosition availablePosition = ArtifactUtils::getArtBackpackPosition(artSetPtr->getHero(), art->getTypeId());
if(availablePosition != ArtifactPosition::PRE_FIRST)
{
destinationPosition = availablePosition;
}
}
else if(ArtifactUtils::isSlotBackpack(artPlace.slot)) else if(ArtifactUtils::isSlotBackpack(artPlace.slot))
{ dstLoc.slot = ArtifactUtils::getArtEquippedPosition(artSetPtr->getHero(), art->getTypeId());
ArtifactPosition availablePosition = ArtifactUtils::getArtAnyPosition(artSetPtr->getHero(), art->getTypeId());
if(availablePosition != ArtifactPosition::PRE_FIRST && availablePosition != ArtifactPosition::BACKPACK_START)
{
destinationPosition = availablePosition;
}
}
if(destinationPosition != ArtifactPosition::PRE_FIRST)
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot),
ArtifactLocation(artSetPtr->getHero()->id, destinationPosition));
}
}
else
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(artSetPtr->getHero()->id, artPlace.slot),
ArtifactLocation(artSetPtr->getHero()->id, ArtifactPosition::TRANSITION_POS));
} }
if(dstLoc.slot != ArtifactPosition::PRE_FIRST)
LOCPLINT->cb->swapArtifacts(srcLoc, dstLoc);
} }
} }
else else
{ {
for(const auto artSlot : ArtifactUtils::unmovableSlots()) for(const auto & artSlot : ArtifactUtils::unmovableSlots())
if(artPlace.slot == artSlot) if(artPlace.slot == artSlot)
{ {
msg = CGI->generaltexth->allTexts[21]; msg = CGI->generaltexth->allTexts[21];
@@ -225,7 +217,7 @@ void CWindowWithArtifacts::clickPressedArtPlaceHero(const CArtifactsOfHeroBase &
if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroBackpack>>) if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroBackpack>>)
{ {
if(!isTransferAllowed && artPlace.getArt() && closeCallback) if(!isTransferAllowed && artPlace.getArt() && !GH.isKeyboardCtrlDown() && !GH.isKeyboardAltDown() && closeCallback)
closeCallback(); closeCallback();
} }
else else
@@ -354,8 +346,8 @@ void CWindowWithArtifacts::enableArtifactsCostumeSwitcher() const
{ {
if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroMain>>) if constexpr(std::is_same_v<decltype(artSetWeak), std::weak_ptr<CArtifactsOfHeroMain>>)
{ {
const auto artSetPtr = artSetWeak.lock(); if(auto artSetPtr = artSetWeak.lock())
artSetPtr->enableArtifactsCostumeSwitcher(); artSetPtr->enableArtifactsCostumeSwitcher();
} }
}, artSet); }, artSet);
} }
@@ -367,16 +359,10 @@ void CWindowWithArtifacts::artifactRemoved(const ArtifactLocation & artLoc)
void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw) void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const ArtifactLocation & destLoc, bool withRedraw)
{ {
auto curState = getState(); const auto pickedArtInst = getPickedArtifact();
if(!curState.has_value())
// Transition state. Nothing to do here. Just skip. Need to wait for final state.
return;
auto pickedArtInst = std::get<const CArtifactInstance*>(curState.value());
auto artifactMovedBody = [this, withRedraw, &destLoc, &pickedArtInst](auto artSetWeak) -> void auto artifactMovedBody = [this, withRedraw, &destLoc, &pickedArtInst](auto artSetWeak) -> void
{ {
auto artSetPtr = artSetWeak.lock(); if(auto artSetPtr = artSetWeak.lock())
if(artSetPtr)
{ {
const auto hero = artSetPtr->getHero(); const auto hero = artSetPtr->getHero();
if(pickedArtInst) if(pickedArtInst)
@@ -446,45 +432,9 @@ void CWindowWithArtifacts::update() const
std::visit(updateSlotBody, artSetWeak); std::visit(updateSlotBody, artSetWeak);
} }
std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> CWindowWithArtifacts::getState() std::optional<CWindowWithArtifacts::ArtifactsOfHeroVar> CWindowWithArtifacts::findAOHbyRef(const CArtifactsOfHeroBase & artsInst)
{ {
const CArtifactInstance * artInst = nullptr; std::optional<ArtifactsOfHeroVar> res;
std::map<const CGHeroInstance*, size_t> pickedCnt;
auto getHeroArtBody = [&artInst, &pickedCnt](auto artSetWeak) -> void
{
auto artSetPtr = artSetWeak.lock();
if(artSetPtr)
{
if(const auto art = artSetPtr->getPickedArtifact())
{
const auto hero = artSetPtr->getHero();
if(pickedCnt.count(hero) == 0)
{
pickedCnt.insert({ hero, hero->artifactsTransitionPos.size() });
artInst = art;
}
}
}
};
for(auto artSetWeak : artSets)
std::visit(getHeroArtBody, artSetWeak);
// The state is possible when the hero has placed an artifact in the ArtifactPosition::TRANSITION_POS,
// and the previous artifact has not yet removed from the ArtifactPosition::TRANSITION_POS.
// This is a transitional state. Then return nullopt.
if(std::accumulate(std::begin(pickedCnt), std::end(pickedCnt), 0, [](size_t accum, const auto & value)
{
return accum + value.second;
}) > 1)
return std::nullopt;
else
return std::make_tuple(pickedCnt.begin()->first, artInst);
}
std::optional<CWindowWithArtifacts::CArtifactsOfHeroPtr> CWindowWithArtifacts::findAOHbyRef(const CArtifactsOfHeroBase & artsInst)
{
std::optional<CArtifactsOfHeroPtr> res;
auto findAOHBody = [&res, &artsInst](auto & artSetWeak) -> void auto findAOHBody = [&res, &artsInst](auto & artSetWeak) -> void
{ {

View File

@@ -19,7 +19,7 @@
class CWindowWithArtifacts : virtual public CWindowObject class CWindowWithArtifacts : virtual public CWindowObject
{ {
public: public:
using CArtifactsOfHeroPtr = std::variant< using ArtifactsOfHeroVar = std::variant<
std::weak_ptr<CArtifactsOfHeroMarket>, std::weak_ptr<CArtifactsOfHeroMarket>,
std::weak_ptr<CArtifactsOfHeroAltar>, std::weak_ptr<CArtifactsOfHeroAltar>,
std::weak_ptr<CArtifactsOfHeroKingdom>, std::weak_ptr<CArtifactsOfHeroKingdom>,
@@ -28,12 +28,12 @@ public:
std::weak_ptr<CArtifactsOfHeroQuickBackpack>>; std::weak_ptr<CArtifactsOfHeroQuickBackpack>>;
using CloseCallback = std::function<void()>; using CloseCallback = std::function<void()>;
std::vector<CArtifactsOfHeroPtr> artSets; std::vector<ArtifactsOfHeroVar> artSets;
CloseCallback closeCallback; CloseCallback closeCallback;
explicit CWindowWithArtifacts(const std::vector<CArtifactsOfHeroPtr> * artSets = nullptr); explicit CWindowWithArtifacts(const std::vector<ArtifactsOfHeroVar> * artSets = nullptr);
void addSet(CArtifactsOfHeroPtr newArtSet); void addSet(ArtifactsOfHeroVar newArtSet);
void addSetAndCallbacks(CArtifactsOfHeroPtr newArtSet); void addSetAndCallbacks(ArtifactsOfHeroVar newArtSet);
void addCloseCallback(const CloseCallback & callback); void addCloseCallback(const CloseCallback & callback);
const CGHeroInstance * getHeroPickedArtifact(); const CGHeroInstance * getHeroPickedArtifact();
const CArtifactInstance * getPickedArtifact(); const CArtifactInstance * getPickedArtifact();
@@ -51,8 +51,7 @@ public:
protected: protected:
void update() const; void update() const;
std::optional<std::tuple<const CGHeroInstance*, const CArtifactInstance*>> getState(); std::optional<ArtifactsOfHeroVar> findAOHbyRef(const CArtifactsOfHeroBase & artsInst);
std::optional<CArtifactsOfHeroPtr> findAOHbyRef(const CArtifactsOfHeroBase & artsInst);
void markPossibleSlots(); void markPossibleSlots();
bool checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade) const; bool checkSpecialArts(const CArtifactInstance & artInst, const CGHeroInstance * hero, bool isTrade) const;
void setCursorAnimation(const CArtifactInstance & artInst); void setCursorAnimation(const CArtifactInstance & artInst);

View File

@@ -19,7 +19,39 @@
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
DLL_LINKAGE bool ArtifactUtils::checkIfSlotValid(const CArtifactSet & artSet, const ArtifactPosition & slot)
{
if(artSet.bearerType() == ArtBearer::HERO)
{
if(isSlotEquipment(slot) || isSlotBackpack(slot) || slot == ArtifactPosition::TRANSITION_POS)
return true;
}
else if(artSet.bearerType() == ArtBearer::ALTAR)
{
if(isSlotBackpack(slot))
return true;
}
else if(artSet.bearerType() == ArtBearer::COMMANDER)
{
if(vstd::contains(commanderSlots(), slot))
return true;
}
else if(artSet.bearerType() == ArtBearer::CREATURE)
{
if(slot == ArtifactPosition::CREATURE_SLOT)
return true;
}
return false;
}
DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid) DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid)
{
if(auto targetSlot = getArtEquippedPosition(target, aid); targetSlot != ArtifactPosition::PRE_FIRST)
return targetSlot;
return getArtBackpackPosition(target, aid);
}
DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtEquippedPosition(const CArtifactSet * target, const ArtifactID & aid)
{ {
const auto * art = aid.toArtifact(); const auto * art = aid.toArtifact();
for(const auto & slot : art->getPossibleSlots().at(target->bearerType())) for(const auto & slot : art->getPossibleSlots().at(target->bearerType()))
@@ -27,7 +59,7 @@ DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtAnyPosition(const CArtifactSet
if(art->canBePutAt(target, slot)) if(art->canBePutAt(target, slot))
return slot; return slot;
} }
return getArtBackpackPosition(target, aid); return ArtifactPosition::PRE_FIRST;
} }
DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid) DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtBackpackPosition(const CArtifactSet * target, const ArtifactID & aid)

View File

@@ -25,8 +25,9 @@ class CMap;
namespace ArtifactUtils namespace ArtifactUtils
{ {
// Calculates where an artifact gets placed when it gets transferred from one hero to another. DLL_LINKAGE bool checkIfSlotValid(const CArtifactSet & artSet, const ArtifactPosition & slot);
DLL_LINKAGE ArtifactPosition getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid); DLL_LINKAGE ArtifactPosition getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid);
DLL_LINKAGE ArtifactPosition getArtEquippedPosition(const CArtifactSet * target, const ArtifactID & aid);
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();

View File

@@ -897,13 +897,7 @@ const CArtifactInstance * CArtifactSet::getAssemblyByConstituent(const ArtifactI
const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
{ {
if(pos == ArtifactPosition::TRANSITION_POS) if(pos == ArtifactPosition::TRANSITION_POS)
{ return &artifactsTransitionPos;
// Always add to the end. Always take from the beginning.
if(artifactsTransitionPos.empty())
return nullptr;
else
return &(*artifactsTransitionPos.begin());
}
if(vstd::contains(artifactsWorn, pos)) if(vstd::contains(artifactsWorn, pos))
return &artifactsWorn.at(pos); return &artifactsWorn.at(pos);
if(ArtifactUtils::isSlotBackpack(pos)) if(ArtifactUtils::isSlotBackpack(pos))
@@ -936,9 +930,7 @@ void CArtifactSet::setNewArtSlot(const ArtifactPosition & slot, ConstTransitiveP
ArtSlotInfo * slotInfo; ArtSlotInfo * slotInfo;
if(slot == ArtifactPosition::TRANSITION_POS) if(slot == ArtifactPosition::TRANSITION_POS)
{ {
// Always add to the end. Always take from the beginning. slotInfo = &artifactsTransitionPos;
artifactsTransitionPos.emplace_back();
slotInfo = &artifactsTransitionPos.back();
} }
else if(ArtifactUtils::isSlotEquipment(slot)) else if(ArtifactUtils::isSlotEquipment(slot))
{ {
@@ -957,8 +949,7 @@ void CArtifactSet::eraseArtSlot(const ArtifactPosition & slot)
{ {
if(slot == ArtifactPosition::TRANSITION_POS) if(slot == ArtifactPosition::TRANSITION_POS)
{ {
assert(!artifactsTransitionPos.empty()); artifactsTransitionPos.artifact = nullptr;
artifactsTransitionPos.erase(artifactsTransitionPos.begin());
} }
else if(ArtifactUtils::isSlotBackpack(slot)) else if(ArtifactUtils::isSlotBackpack(slot))
{ {

View File

@@ -194,7 +194,7 @@ public:
std::vector<ArtSlotInfo> artifactsInBackpack; //hero's artifacts from bag 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::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 ArtSlotInfo artifactsTransitionPos; // Used as transition position for dragAndDrop artifact exchange
void setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked); void setNewArtSlot(const ArtifactPosition & slot, ConstTransitivePtr<CArtifactInstance> art, bool locked);
void eraseArtSlot(const ArtifactPosition & slot); void eraseArtSlot(const ArtifactPosition & slot);

View File

@@ -2721,10 +2721,16 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati
if(!isAllowedExchange(src.artHolder, dst.artHolder)) if(!isAllowedExchange(src.artHolder, dst.artHolder))
COMPLAIN_RET("That heroes cannot make any exchange!"); COMPLAIN_RET("That heroes cannot make any exchange!");
COMPLAIN_RET_FALSE_IF(!ArtifactUtils::checkIfSlotValid(*srcArtSet, src.slot), "moveArtifact: wrong artifact source slot");
const auto srcArtifact = srcArtSet->getArt(src.slot); const auto srcArtifact = srcArtSet->getArt(src.slot);
const auto dstArtifact = dstArtSet->getArt(dst.slot); auto dstSlot = dst.slot;
if(dstSlot == ArtifactPosition::FIRST_AVAILABLE)
dstSlot = ArtifactUtils::getArtAnyPosition(dstArtSet, srcArtifact->getTypeId());
if(!ArtifactUtils::checkIfSlotValid(*dstArtSet, dstSlot))
return true;
const auto dstArtifact = dstArtSet->getArt(dstSlot);
const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtifact != nullptr; const bool isDstSlotOccupied = dstArtSet->bearerType() == ArtBearer::ALTAR ? false : dstArtifact != nullptr;
const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dst.slot) : false; const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dstSlot) : false;
if(srcArtifact == nullptr) if(srcArtifact == nullptr)
COMPLAIN_RET("No artifact to move!"); COMPLAIN_RET("No artifact to move!");
@@ -2733,23 +2739,23 @@ bool CGameHandler::moveArtifact(const PlayerColor & player, const ArtifactLocati
// Check if src/dest slots are appropriate for the artifacts exchanged. // Check if src/dest slots are appropriate for the artifacts exchanged.
// Moving to the backpack is always allowed. // Moving to the backpack is always allowed.
if((!srcArtifact || !isDstSlotBackpack) && !srcArtifact->canBePutAt(dstArtSet, dst.slot, true)) if((!srcArtifact || !isDstSlotBackpack) && !srcArtifact->canBePutAt(dstArtSet, dstSlot, true))
COMPLAIN_RET("Cannot move artifact!"); COMPLAIN_RET("Cannot move artifact!");
auto srcSlotInfo = srcArtSet->getSlot(src.slot); auto srcSlotInfo = srcArtSet->getSlot(src.slot);
auto dstSlotInfo = dstArtSet->getSlot(dst.slot); auto dstSlotInfo = dstArtSet->getSlot(dstSlot);
if((srcSlotInfo && srcSlotInfo->locked) || (dstSlotInfo && dstSlotInfo->locked)) if((srcSlotInfo && srcSlotInfo->locked) || (dstSlotInfo && dstSlotInfo->locked))
COMPLAIN_RET("Cannot move artifact locks."); COMPLAIN_RET("Cannot move artifact locks.");
if(isDstSlotBackpack && srcArtifact->artType->isBig()) if(isDstSlotBackpack && srcArtifact->artType->isBig())
COMPLAIN_RET("Cannot put big artifacts in backpack!"); COMPLAIN_RET("Cannot put big artifacts in backpack!");
if(src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4) if(src.slot == ArtifactPosition::MACH4 || dstSlot == ArtifactPosition::MACH4)
COMPLAIN_RET("Cannot move catapult!"); COMPLAIN_RET("Cannot move catapult!");
if(isDstSlotBackpack && !ArtifactUtils::isBackpackFreeSlots(dstArtSet)) if(isDstSlotBackpack && !ArtifactUtils::isBackpackFreeSlots(dstArtSet))
COMPLAIN_RET("Backpack is full!"); COMPLAIN_RET("Backpack is full!");
auto dstSlot = std::min(dst.slot, ArtifactPosition(ArtifactPosition::BACKPACK_START + dstArtSet->artifactsInBackpack.size())); dstSlot = std::min(dstSlot, ArtifactPosition(ArtifactPosition::BACKPACK_START + dstArtSet->artifactsInBackpack.size()));
if(src.slot == dstSlot && src.artHolder == dst.artHolder) if(src.slot == dstSlot && src.artHolder == dst.artHolder)
COMPLAIN_RET("Won't move artifact: Dest same as source!"); COMPLAIN_RET("Won't move artifact: Dest same as source!");