1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-12-20 20:23:03 +02:00

bulk move artifacts only equipped, only backpack

This commit is contained in:
SoundSSGood 2023-07-24 19:09:17 +03:00
parent c6a86d9a5f
commit a83f290e13
16 changed files with 99 additions and 53 deletions

View File

@ -174,9 +174,9 @@ void CCallback::assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition
sendRequest(&aa); 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); sendRequest(&bma);
} }

View File

@ -108,7 +108,7 @@ public:
// Moves all artifacts from one hero to another // 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 class CBattleCallback : public IBattleCallback
@ -171,7 +171,7 @@ public:
bool dismissHero(const CGHeroInstance * hero) override; bool dismissHero(const CGHeroInstance * hero) override;
bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override; bool swapArtifacts(const ArtifactLocation &l1, const ArtifactLocation &l2) override;
void assembleArtifacts(const CGHeroInstance * hero, ArtifactPosition artifactSlot, bool assemble, ArtifactID assembleTo) 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; void eraseArtifactByClient(const ArtifactLocation & al) override;
bool buildBuilding(const CGTownInstance *town, BuildingID buildingID) 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; void recruitCreatures(const CGDwelling * obj, const CArmedInstance * dst, CreatureID ID, ui32 amount, si32 level=-1) override;

View File

@ -654,6 +654,11 @@ std::function<void()> CExchangeController::onSwapArtifacts()
{ {
return [&]() return [&]()
{ {
if(GH.isKeyboardCtrlDown())
cb->bulkMoveArtifacts(left->id, right->id, true, true, false);
else if(GH.isKeyboardShiftDown())
cb->bulkMoveArtifacts(left->id, right->id, true, false, true);
else
cb->bulkMoveArtifacts(left->id, right->id, true); cb->bulkMoveArtifacts(left->id, right->id, true);
}; };
} }
@ -810,10 +815,13 @@ void CExchangeController::moveArtifacts(bool leftToRight)
const CGHeroInstance * target = leftToRight ? right : left; const CGHeroInstance * target = leftToRight ? right : left;
if(source->tempOwner != cb->getPlayerID()) if(source->tempOwner != cb->getPlayerID())
{
return; return;
}
if(GH.isKeyboardCtrlDown())
cb->bulkMoveArtifacts(source->id, target->id, false, true, false);
else if(GH.isKeyboardShiftDown())
cb->bulkMoveArtifacts(source->id, target->id, false, false, true);
else
cb->bulkMoveArtifacts(source->id, target->id, false); cb->bulkMoveArtifacts(source->id, target->id, false);
} }

View File

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

View File

@ -246,11 +246,13 @@ struct DLL_LINKAGE ArtSlotInfo
class DLL_LINKAGE CArtifactSet class DLL_LINKAGE CArtifactSet
{ {
public: public:
using ArtPlacementMap = std::map<CArtifactInstance*, ArtifactPosition>;
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 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); void eraseArtSlot(const ArtifactPosition & slot);
const ArtSlotInfo * getSlot(const ArtifactPosition & pos) const; 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; unsigned getArtPosCount(const ArtifactID & aid, bool onlyWorn = true, bool searchBackpackAssemblies = true, bool allowLocked = true) const;
virtual ArtBearer::ArtBearer bearerType() const = 0; 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 void removeArtifact(ArtifactPosition slot);
virtual ~CArtifactSet(); virtual ~CArtifactSet();

View File

@ -55,6 +55,16 @@ const std::vector<CCombinedArtifactInstance::PartInfo> & CCombinedArtifactInstan
return partsInfo; 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 SpellID CScrollArtifactInstance::getScrollSpellID() const
{ {
auto artInst = static_cast<const CArtifactInstance*>(this); auto artInst = static_cast<const CArtifactInstance*>(this);
@ -163,7 +173,7 @@ bool CArtifactInstance::isCombined() const
void CArtifactInstance::putAt(const ArtifactLocation & al) void CArtifactInstance::putAt(const ArtifactLocation & al)
{ {
al.getHolderArtSet()->putArtifact(al.slot, this); addPlacementMap(al.getHolderArtSet()->putArtifact(al.slot, this));
} }
void CArtifactInstance::removeFrom(const ArtifactLocation & al) void CArtifactInstance::removeFrom(const ArtifactLocation & al)

View File

@ -12,6 +12,7 @@
#include "bonuses/CBonusSystemNode.h" #include "bonuses/CBonusSystemNode.h"
#include "GameConstants.h" #include "GameConstants.h"
#include "ConstTransitivePtr.h" #include "ConstTransitivePtr.h"
#include "CArtHandler.h"
VCMI_LIB_NAMESPACE_BEGIN VCMI_LIB_NAMESPACE_BEGIN
@ -39,6 +40,7 @@ public:
bool isPart(const CArtifactInstance * supposedPart) const; bool isPart(const CArtifactInstance * supposedPart) const;
std::vector<PartInfo> & getPartsInfo(); std::vector<PartInfo> & getPartsInfo();
const std::vector<PartInfo> & getPartsInfo() const; const std::vector<PartInfo> & getPartsInfo() const;
void addPlacementMap(CArtifactSet::ArtPlacementMap & placementMap);
template <typename Handler> void serialize(Handler & h, const int version) template <typename Handler> void serialize(Handler & h, const int version)
{ {

View File

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

View File

@ -121,7 +121,7 @@ public:
void setArmyObj(const CArmedInstance *ArmyObj); void setArmyObj(const CArmedInstance *ArmyObj);
virtual void giveStackExp(TExpType exp); virtual void giveStackExp(TExpType exp);
bool valid(bool allowUnrandomized) const; 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; void removeArtifact(ArtifactPosition pos) override;
ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet ArtBearer::ArtBearer bearerType() const override; //from CArtifactSet
virtual std::string nodeName() const override; //from CBonusSystemnode virtual std::string nodeName() const override; //from CBonusSystemnode

View File

@ -2413,12 +2413,16 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer
ObjectInstanceID srcHero; ObjectInstanceID srcHero;
ObjectInstanceID dstHero; ObjectInstanceID dstHero;
bool swap = false; bool swap = false;
bool equipped = true;
bool backpack = true;
BulkExchangeArtifacts() = default; 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) : srcHero(srcHero)
, dstHero(dstHero) , dstHero(dstHero)
, swap(swap) , swap(swap)
, equipped(equipped)
, backpack(backpack)
{ {
} }
@ -2430,6 +2434,8 @@ struct DLL_LINKAGE BulkExchangeArtifacts : public CPackForServer
h & srcHero; h & srcHero;
h & dstHero; h & dstHero;
h & swap; h & swap;
h & equipped;
h & backpack;
} }
}; };

View File

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

View File

@ -229,7 +229,7 @@ public:
void initHero(CRandomGenerator & rand); void initHero(CRandomGenerator & rand);
void initHero(CRandomGenerator & rand, const HeroTypeID & SUBID); 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 removeArtifact(ArtifactPosition pos) override;
void initExp(CRandomGenerator & rand); void initExp(CRandomGenerator & rand);
void initArmy(CRandomGenerator & rand, IArmyDescriptor *dst = nullptr); void initArmy(CRandomGenerator & rand, IArmyDescriptor *dst = nullptr);

View File

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

View File

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

View File

@ -131,7 +131,7 @@ public:
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override; void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override;
void removeArtifact(const ArtifactLocation &al) override; void removeArtifact(const ArtifactLocation &al) override;
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) 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); bool eraseArtifactByClient(const ArtifactLocation & al);
void synchronizeArtifactHandlerLists(); void synchronizeArtifactHandlerLists();

View File

@ -132,7 +132,7 @@ void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack) void ApplyGhNetPackVisitor::visitBulkExchangeArtifacts(BulkExchangeArtifacts & pack)
{ {
gh.throwIfWrongOwner(&pack, pack.srcHero); gh.throwIfWrongOwner(&pack, pack.srcHero);
result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap); result = gh.bulkMoveArtifacts(pack.srcHero, pack.dstHero, pack.swap, pack.equipped, pack.backpack);
} }
void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack) void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)