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

ArtifactLocation now use ID for artHolder identification part2

This commit is contained in:
SoundSSGood 2023-10-14 22:00:39 +03:00
parent 61fc236d79
commit ab2f6abb87
29 changed files with 216 additions and 273 deletions

View File

@ -996,21 +996,21 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
for(auto p : h->artifactsWorn)
{
if(p.second.artifact)
allArtifacts.push_back(ArtifactLocation(h, p.first));
allArtifacts.push_back(ArtifactLocation(h->id, p.first));
}
}
for(auto slot : h->artifactsInBackpack)
allArtifacts.push_back(ArtifactLocation(h, h->getArtPos(slot.artifact)));
allArtifacts.push_back(ArtifactLocation(h->id, h->getArtPos(slot.artifact)));
if(otherh)
{
for(auto p : otherh->artifactsWorn)
{
if(p.second.artifact)
allArtifacts.push_back(ArtifactLocation(otherh, p.first));
allArtifacts.push_back(ArtifactLocation(otherh->id, p.first));
}
for(auto slot : otherh->artifactsInBackpack)
allArtifacts.push_back(ArtifactLocation(otherh, otherh->getArtPos(slot.artifact)));
allArtifacts.push_back(ArtifactLocation(otherh->id, otherh->getArtPos(slot.artifact)));
}
//we give stuff to one hero or another, depending on giveStuffToFirstHero
@ -1022,13 +1022,13 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
for(auto location : allArtifacts)
{
if(location.relatedObj() == target && ArtifactUtils::isSlotEquipment(location.slot))
if(location.artHolder == target->id && ArtifactUtils::isSlotEquipment(location.slot))
continue; //don't reequip artifact we already wear
if(location.slot == ArtifactPosition::MACH4) // don't attempt to move catapult
continue;
auto s = location.getSlot();
auto s = cb->getHero(location.artHolder)->getSlot(location.slot);
if(!s || s->locked) //we can't move locks
continue;
auto artifact = s->artifact;
@ -1039,9 +1039,9 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
bool emptySlotFound = false;
for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType()))
{
ArtifactLocation destLocation(target, slot);
if(target->isPositionFree(slot) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move
if(target->isPositionFree(slot) && artifact->canBePutAt(target, slot, true)) //combined artifacts are not always allowed to move
{
ArtifactLocation destLocation(target->id, slot);
cb->swapArtifacts(location, destLocation); //just put into empty slot
emptySlotFound = true;
changeMade = true;
@ -1055,11 +1055,11 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
auto otherSlot = target->getSlot(slot);
if(otherSlot && otherSlot->artifact) //we need to exchange artifact for better one
{
ArtifactLocation destLocation(target, slot);
//if that artifact is better than what we have, pick it
if(compareArtifacts(artifact, otherSlot->artifact) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move
if(compareArtifacts(artifact, otherSlot->artifact) && artifact->canBePutAt(target, slot, true)) //combined artifacts are not always allowed to move
{
cb->swapArtifacts(location, ArtifactLocation(target, target->getArtPos(otherSlot->artifact)));
ArtifactLocation destLocation(target->id, slot);
cb->swapArtifacts(location, ArtifactLocation(target->id, target->getArtPos(otherSlot->artifact)));
changeMade = true;
break;
}

View File

@ -1167,21 +1167,21 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
for(auto p : h->artifactsWorn)
{
if(p.second.artifact)
allArtifacts.push_back(ArtifactLocation(h, p.first));
allArtifacts.push_back(ArtifactLocation(h->id, p.first));
}
}
for(auto slot : h->artifactsInBackpack)
allArtifacts.push_back(ArtifactLocation(h, h->getArtPos(slot.artifact)));
allArtifacts.push_back(ArtifactLocation(h->id, h->getArtPos(slot.artifact)));
if(otherh)
{
for(auto p : otherh->artifactsWorn)
{
if(p.second.artifact)
allArtifacts.push_back(ArtifactLocation(otherh, p.first));
allArtifacts.push_back(ArtifactLocation(otherh->id, p.first));
}
for(auto slot : otherh->artifactsInBackpack)
allArtifacts.push_back(ArtifactLocation(otherh, otherh->getArtPos(slot.artifact)));
allArtifacts.push_back(ArtifactLocation(otherh->id, otherh->getArtPos(slot.artifact)));
}
//we give stuff to one hero or another, depending on giveStuffToFirstHero
@ -1196,10 +1196,10 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
if(location.slot == ArtifactPosition::MACH4 || location.slot == ArtifactPosition::SPELLBOOK)
continue; // don't attempt to move catapult and spellbook
if(location.relatedObj() == target && ArtifactUtils::isSlotEquipment(location.slot))
if(location.artHolder == target->id && ArtifactUtils::isSlotEquipment(location.slot))
continue; //don't reequip artifact we already wear
auto s = location.getSlot();
auto s = cb->getHero(location.artHolder)->getSlot(location.slot);
if(!s || s->locked) //we can't move locks
continue;
auto artifact = s->artifact;
@ -1210,9 +1210,9 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
bool emptySlotFound = false;
for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType()))
{
ArtifactLocation destLocation(target, slot);
if(target->isPositionFree(slot) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move
if(target->isPositionFree(slot) && artifact->canBePutAt(target, slot, true)) //combined artifacts are not always allowed to move
{
ArtifactLocation destLocation(target->id, slot);
cb->swapArtifacts(location, destLocation); //just put into empty slot
emptySlotFound = true;
changeMade = true;
@ -1226,11 +1226,11 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
auto otherSlot = target->getSlot(slot);
if(otherSlot && otherSlot->artifact) //we need to exchange artifact for better one
{
ArtifactLocation destLocation(target, slot);
//if that artifact is better than what we have, pick it
if(compareArtifacts(artifact, otherSlot->artifact) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move
if(compareArtifacts(artifact, otherSlot->artifact) && artifact->canBePutAt(target, slot, true)) //combined artifacts are not always allowed to move
{
cb->swapArtifacts(location, ArtifactLocation(target, target->getArtPos(otherSlot->artifact)));
ArtifactLocation destLocation(target->id, slot);
cb->swapArtifacts(location, ArtifactLocation(target->id, target->getArtPos(otherSlot->artifact)));
changeMade = true;
break;
}

View File

@ -1753,8 +1753,7 @@ void CPlayerInterface::requestReturningToMainMenu(bool won)
void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
{
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
if(hero)
if(auto hero = cb->getHero(al.artHolder))
{
auto art = hero->getArt(al.slot);
if(art == nullptr)
@ -1770,15 +1769,13 @@ void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
void CPlayerInterface::artifactPut(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
adventureInt->onHeroChanged(hero);
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
}
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
adventureInt->onHeroChanged(hero);
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
artWin->artifactRemoved(al);
@ -1789,8 +1786,7 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
auto hero = std::visit(HeroObjectRetriever(), dst.artHolder);
adventureInt->onHeroChanged(hero);
adventureInt->onHeroChanged(cb->getHero(dst.artHolder));
bool redraw = true;
// If a bulk transfer has arrived, then redrawing only the last art movement.
@ -1815,8 +1811,7 @@ void CPlayerInterface::bulkArtMovementStart(size_t numOfArts)
void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
adventureInt->onHeroChanged(hero);
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
artWin->artifactAssembled(al);
@ -1825,8 +1820,7 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
{
EVENT_HANDLER_CALLED_BY_CLIENT;
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
adventureInt->onHeroChanged(hero);
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
artWin->artifactDisassembled(al);

View File

@ -267,14 +267,14 @@ void ApplyClientNetPackVisitor::visitBulkSmartRebalanceStacks(BulkSmartRebalance
void ApplyClientNetPackVisitor::visitPutArtifact(PutArtifact & pack)
{
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactPut, pack.al);
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactPut, pack.al);
if(pack.askAssemble)
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::askToAssembleArtifact, pack.al);
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::askToAssembleArtifact, pack.al);
}
void ApplyClientNetPackVisitor::visitEraseArtifact(EraseArtifact & pack)
{
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactRemoved, pack.al);
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactRemoved, pack.al);
}
void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack)
@ -286,16 +286,16 @@ void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack)
callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst);
};
moveArtifact(pack.src.owningPlayer());
if(pack.src.owningPlayer() != pack.dst.owningPlayer())
moveArtifact(pack.dst.owningPlayer());
moveArtifact(cl.getOwner(pack.src.artHolder));
if(cl.getOwner(pack.src.artHolder) != cl.getOwner(pack.dst.artHolder))
moveArtifact(cl.getOwner(pack.dst.artHolder));
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
}
void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
{
auto applyMove = [this, &pack](std::vector<BulkMoveArtifacts::LinkedSlots> & artsPack) -> void
/*auto applyMove = [this, &pack](std::vector<BulkMoveArtifacts::LinkedSlots> & artsPack) -> void
{
for(auto & slotToMove : artsPack)
{
@ -316,19 +316,19 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
applyMove(pack.artsPack0);
if(pack.swap)
applyMove(pack.artsPack1);
applyMove(pack.artsPack1);*/
}
void ApplyClientNetPackVisitor::visitAssembledArtifact(AssembledArtifact & pack)
{
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactAssembled, pack.al);
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactAssembled, pack.al);
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
}
void ApplyClientNetPackVisitor::visitDisassembledArtifact(DisassembledArtifact & pack)
{
callInterfaceIfPresent(cl, pack.al.owningPlayer(), &IGameEventsReceiver::artifactDisassembled, pack.al);
callInterfaceIfPresent(cl, cl.getOwner(pack.al.artHolder), &IGameEventsReceiver::artifactDisassembled, pack.al);
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
}

View File

@ -121,10 +121,10 @@ void CCommanderArtPlace::returnArtToHeroCallback()
}
else
{
ArtifactLocation src(commanderOwner->commander.get(), artifactPos);
ArtifactLocation dst(commanderOwner, freeSlot);
ArtifactLocation src(commanderOwner->id, artifactPos);
ArtifactLocation dst(commanderOwner->id, freeSlot);
if(ourArt->canBePutAt(dst, true))
if(ourArt->canBePutAt(commanderOwner, freeSlot, true))
{
LOCPLINT->cb->swapArtifacts(src, dst);
setArtifact(nullptr);

View File

@ -72,7 +72,7 @@ void CArtifactsOfHeroAltar::pickUpArtifact(CHeroArtPlace & artPlace)
if(ArtifactUtils::isSlotBackpack(pickedArtFromSlot))
pickedArtFromSlot = curHero->getSlotByInstance(art);
assert(pickedArtFromSlot != ArtifactPosition::PRE_FIRST);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, pickedArtFromSlot), ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, pickedArtFromSlot), ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
}
}
@ -89,7 +89,7 @@ void CArtifactsOfHeroAltar::pickedArtMoveToAltar(const ArtifactPosition & slot)
if(ArtifactUtils::isSlotBackpack(slot) || ArtifactUtils::isSlotEquipment(slot) || slot == ArtifactPosition::TRANSITION_POS)
{
assert(curHero->getSlot(slot)->getArt());
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, slot), ArtifactLocation(curHero, pickedArtFromSlot));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, slot), ArtifactLocation(curHero->id, pickedArtFromSlot));
pickedArtFromSlot = ArtifactPosition::PRE_FIRST;
}
}

View File

@ -80,8 +80,8 @@ void CArtifactsOfHeroBackpack::swapArtifacts(const ArtifactLocation & srcLoc, co
void CArtifactsOfHeroBackpack::pickUpArtifact(CHeroArtPlace & artPlace)
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, artPlace.slot),
ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot),
ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
}
void CArtifactsOfHeroBackpack::scrollBackpack(int offset)

View File

@ -39,11 +39,11 @@ void CArtifactsOfHeroBase::putBackPickedArtifact()
auto slot = ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->getTypeId());
if(slot == ArtifactPosition::PRE_FIRST)
{
LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
}
else
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS), ArtifactLocation(curHero, slot));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS), ArtifactLocation(curHero->id, slot));
}
}
if(putBackPickedArtCallback)
@ -178,7 +178,7 @@ void CArtifactsOfHeroBase::scrollBackpackForArtSet(int offset, const CArtifactSe
void CArtifactsOfHeroBase::markPossibleSlots(const CArtifactInstance * art, bool assumeDestRemoved)
{
for(auto artPlace : artWorn)
artPlace.second->selectSlot(art->artType->canBePutAt(curHero, artPlace.second->slot, assumeDestRemoved));
artPlace.second->selectSlot(art->canBePutAt(curHero, artPlace.second->slot, assumeDestRemoved));
}
void CArtifactsOfHeroBase::unmarkSlots()

View File

@ -13,6 +13,7 @@
#include "Buttons.h"
#include "../CPlayerInterface.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../CCallback.h"
#include "../../lib/networkPacks/ArtifactLocation.h"
@ -56,7 +57,7 @@ void CArtifactsOfHeroKingdom::swapArtifacts(const ArtifactLocation & srcLoc, con
void CArtifactsOfHeroKingdom::pickUpArtifact(CHeroArtPlace & artPlace)
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, artPlace.slot),
ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot),
ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
}

View File

@ -11,6 +11,7 @@
#include "CArtifactsOfHeroMain.h"
#include "../CPlayerInterface.h"
#include "../../lib/mapObjects/CGHeroInstance.h"
#include "../../CCallback.h"
#include "../../lib/networkPacks/ArtifactLocation.h"
@ -36,6 +37,6 @@ void CArtifactsOfHeroMain::swapArtifacts(const ArtifactLocation & srcLoc, const
void CArtifactsOfHeroMain::pickUpArtifact(CHeroArtPlace & artPlace)
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, artPlace.slot),
ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot),
ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
}

View File

@ -196,7 +196,7 @@ bool CGarrisonSlot::highlightOrDropArtifact()
artSelected = true;
if (myStack) // try dropping the artifact only if the slot isn't empty
{
ArtifactLocation src(srcHero, ArtifactPosition::TRANSITION_POS);
/*ArtifactLocation src(srcHero, ArtifactPosition::TRANSITION_POS);
ArtifactLocation dst(myStack, ArtifactPosition::CREATURE_SLOT);
if(pickedArtInst->canBePutAt(dst, true))
{ //equip clicked stack
@ -208,7 +208,7 @@ bool CGarrisonSlot::highlightOrDropArtifact()
ArtifactUtils::getArtBackpackPosition(srcHero, dst.getArt()->getTypeId())));
}
LOCPLINT->cb->swapArtifacts(src, dst);
}
}*/
}
}
}

View File

@ -122,8 +122,8 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst
if(pickedArtInst)
{
auto srcLoc = ArtifactLocation(heroPickedArt, ArtifactPosition::TRANSITION_POS);
auto dstLoc = ArtifactLocation(hero, artPlace.slot);
auto srcLoc = ArtifactLocation(heroPickedArt->id, ArtifactPosition::TRANSITION_POS);
auto dstLoc = ArtifactLocation(hero->id, artPlace.slot);
if(ArtifactUtils::isSlotBackpack(artPlace.slot))
{
@ -141,7 +141,7 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst
}
}
// Check if artifact transfer is possible
else if(pickedArtInst->canBePutAt(dstLoc, true) && (!artPlace.getArt() || hero->tempOwner == LOCPLINT->playerID))
else if(pickedArtInst->canBePutAt(hero, artPlace.slot, true) && (!artPlace.getArt() || hero->tempOwner == LOCPLINT->playerID))
{
isTransferAllowed = true;
}
@ -270,7 +270,7 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
// we have a different artifact may look surprising... but it's valid.
auto pickedArtInst = std::get<const CArtifactInstance*>(curState.value());
assert(!pickedArtInst || destLoc.isHolder(std::get<const CGHeroInstance*>(curState.value())));
assert(!pickedArtInst || destLoc.artHolder == std::get<const CGHeroInstance*>(curState.value())->id);
auto artifactMovedBody = [this, withRedraw, &destLoc, &pickedArtInst](auto artSetWeak) -> void
{
@ -316,7 +316,7 @@ void CWindowWithArtifacts::artifactMoved(const ArtifactLocation & srcLoc, const
}
// Make sure the status bar is updated so it does not display old text
if(destLoc.getHolderArtSet() == hero)
if(destLoc.artHolder == hero->id)
{
if(auto artPlace = artSetPtr->getArtPlace(destLoc.slot))
artPlace->hover(true);

View File

@ -974,7 +974,7 @@ void CStackWindow::removeStackArtifact(ArtifactPosition pos)
const auto slot = ArtifactUtils::getArtBackpackPosition(info->owner, art->getTypeId());
if(slot != ArtifactPosition::PRE_FIRST)
{
LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), ArtifactLocation(info->owner, slot));
//LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), ArtifactLocation(info->owner->id, slot));
stackArtifactButton.reset();
stackArtifactHelp.reset();
stackArtifactIcon.reset();
@ -982,3 +982,4 @@ void CStackWindow::removeStackArtifact(ArtifactPosition pos)
}
}

View File

@ -336,10 +336,10 @@ void CHeroWindow::commanderWindow()
const auto freeSlot = ArtifactUtils::getArtAnyPosition(curHero->commander, pickedArtInst->getTypeId());
if(vstd::contains(ArtifactUtils::commanderSlots(), freeSlot)) // We don't want to put it in commander's backpack!
{
ArtifactLocation src(hero, ArtifactPosition::TRANSITION_POS);
ArtifactLocation dst(curHero->commander.get(), freeSlot);
if(pickedArtInst->canBePutAt(dst, true))
ArtifactLocation src(hero->id, ArtifactPosition::TRANSITION_POS);
ArtifactLocation dst(curHero->id, freeSlot);
// TODO add ->commander.get() !!!
/*if(pickedArtInst->canBePutAt(dst, true))
{ //equip clicked stack
if(dst.getArt())
{
@ -347,7 +347,7 @@ void CHeroWindow::commanderWindow()
ArtifactUtils::getArtBackpackPosition(hero, pickedArtInst->getTypeId())));
}
LOCPLINT->cb->swapArtifacts(src, dst);
}
}*/
}
}
else

View File

@ -191,8 +191,8 @@ void CTradeWindow::CTradeableItem::clickPressed(const Point & cursorPosition)
const auto hero = aw->arts->getHero();
const auto slot = hero->getSlotByInstance(art);
assert(slot != ArtifactPosition::PRE_FIRST);
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero, slot),
ArtifactLocation(hero, ArtifactPosition::TRANSITION_POS));
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, slot),
ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS));
aw->arts->pickedArtFromSlot = slot;
aw->arts->artifactsOnAltar.erase(art);
setID(-1);

View File

@ -155,9 +155,9 @@ void CArtifactInstance::setId(ArtifactInstanceID id)
this->id = id;
}
bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved) const
bool CArtifactInstance::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const
{
return artType->canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved);
return artType->canBePutAt(artSet, slot, assumeDestRemoved);
}
bool CArtifactInstance::isCombined() const
@ -165,15 +165,15 @@ bool CArtifactInstance::isCombined() const
return artType->isCombined();
}
void CArtifactInstance::putAt(const ArtifactLocation & al)
void CArtifactInstance::putAt(CArtifactSet & set, const ArtifactPosition slot)
{
auto placementMap = al.getHolderArtSet()->putArtifact(al.slot, this);
auto placementMap = set.putArtifact(slot, this);
addPlacementMap(placementMap);
}
void CArtifactInstance::removeFrom(const ArtifactLocation & al)
void CArtifactInstance::removeFrom(CArtifactSet & set, const ArtifactPosition slot)
{
al.getHolderArtSet()->removeArtifact(al.slot);
set.removeArtifact(slot);
for(auto & part : partsInfo)
{
if(part.slot != ArtifactPosition::PRE_FIRST)
@ -181,10 +181,10 @@ void CArtifactInstance::removeFrom(const ArtifactLocation & al)
}
}
void CArtifactInstance::move(const ArtifactLocation & src, const ArtifactLocation & dst)
void CArtifactInstance::move(CArtifactSet & srcSet, const ArtifactPosition srcSlot, CArtifactSet & dstSet, const ArtifactPosition dstSlot)
{
removeFrom(src);
putAt(dst);
removeFrom(srcSet, srcSlot);
putAt(dstSet, dstSlot);
}
void CArtifactInstance::deserializationFix()

View File

@ -84,11 +84,12 @@ public:
ArtifactInstanceID getId() const;
void setId(ArtifactInstanceID id);
bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const;
bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE,
bool assumeDestRemoved = false) const;
bool isCombined() const;
void putAt(const ArtifactLocation & al);
void removeFrom(const ArtifactLocation & al);
void move(const ArtifactLocation & src, const ArtifactLocation & dst);
void putAt(CArtifactSet & set, const ArtifactPosition slot);
void removeFrom(CArtifactSet & set, const ArtifactPosition slot);
void move(CArtifactSet & srcSet, const ArtifactPosition srcSlot, CArtifactSet & dstSet, const ArtifactPosition dstSlot);
void deserializationFix();
template <typename Handler> void serialize(Handler & h, const int version)

View File

@ -870,7 +870,7 @@ ArtBearer::ArtBearer CStackInstance::bearerType() const
CStackInstance::ArtPlacementMap CStackInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
{
assert(!getArt(pos));
assert(art->artType->canBePutAt(this, pos));
assert(art->canBePutAt(this, pos));
attachTo(*art);
return CArtifactSet::putArtifact(pos, art);

View File

@ -2103,7 +2103,7 @@ bool CGameState::giveHeroArtifact(CGHeroInstance * h, const ArtifactID & aid)
auto slot = ArtifactUtils::getArtAnyPosition(h, aid);
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
{
ai->putAt(ArtifactLocation(h, slot));
ai->putAt(*h, slot);
return true;
}
else

View File

@ -134,9 +134,9 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(std::vector<CampaignHeroR
bool takeable = travelOptions.artifactsKeptByHero.count(art->artType->getId());
ArtifactLocation al(hero, artifactPosition);
if(!takeable && !al.getSlot()->locked) //don't try removing locked artifacts -> it crashes #1719
al.removeArtifact();
ArtifactLocation al(hero->id, artifactPosition);
if(!takeable && !hero->getSlot(al.slot)->locked) //don't try removing locked artifacts -> it crashes #1719
hero->getArt(al.slot)->removeFrom(*hero, al.slot);
};
// process on copy - removal of artifact will invalidate container
@ -300,7 +300,7 @@ void CGameStateCampaign::giveCampaignBonusToHero(CGHeroInstance * hero)
CArtifactInstance * scroll = ArtifactUtils::createScroll(SpellID(curBonus->info2));
const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId());
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
scroll->putAt(ArtifactLocation(hero, slot));
scroll->putAt(*hero, slot);
else
logGlobal->error("Cannot give starting scroll - no free slots!");
break;

View File

@ -1087,7 +1087,7 @@ std::string CGHeroInstance::getBiographyTextID() const
CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
{
assert(art->artType->canBePutAt(this, pos));
assert(art->canBePutAt(this, pos));
if(ArtifactUtils::isSlotEquipment(pos))
attachTo(*art);
@ -1130,7 +1130,7 @@ void CGHeroInstance::removeSpellbook()
if(hasSpellbook())
{
ArtifactLocation(this, ArtifactPosition(ArtifactPosition::SPELLBOOK)).removeArtifact();
getArt(ArtifactPosition::SPELLBOOK)->removeFrom(*this, ArtifactPosition::SPELLBOOK);
}
}

View File

@ -144,7 +144,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const
{
if(h->hasArt(elem))
{
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(elem, false)));
cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(elem, false)));
}
else
{
@ -153,7 +153,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const
auto parts = assembly->getPartsInfo();
// Remove the assembly
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(assembly)));
cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(assembly)));
// Disassemble this backpack artifact
for(const auto & ci : parts)

View File

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

View File

@ -1574,67 +1574,6 @@ struct GetBase
}
};
void ArtifactLocation::removeArtifact()
{
CArtifactInstance *a = getArt();
assert(a);
a->removeFrom(*this);
}
const CArmedInstance * ArtifactLocation::relatedObj() const
{
return std::visit(ObjectRetriever(), artHolder);
}
PlayerColor ArtifactLocation::owningPlayer() const
{
const auto * obj = relatedObj();
return obj ? obj->tempOwner : PlayerColor::NEUTRAL;
}
CArtifactSet *ArtifactLocation::getHolderArtSet()
{
return std::visit(GetBase<CArtifactSet>(), artHolder);
}
CBonusSystemNode *ArtifactLocation::getHolderNode()
{
return std::visit(GetBase<CBonusSystemNode>(), artHolder);
}
const CArtifactInstance *ArtifactLocation::getArt() const
{
const auto * s = getSlot();
if(s)
return s->getArt();
else
return nullptr;
}
CArtifactSet * ArtifactLocation::getHolderArtSet() const
{
auto * t = const_cast<ArtifactLocation *>(this);
return t->getHolderArtSet();
}
const CBonusSystemNode * ArtifactLocation::getHolderNode() const
{
auto * t = const_cast<ArtifactLocation *>(this);
return t->getHolderNode();
}
CArtifactInstance *ArtifactLocation::getArt()
{
const ArtifactLocation *t = this;
return const_cast<CArtifactInstance*>(t->getArt());
}
const ArtSlotInfo *ArtifactLocation::getSlot() const
{
return getHolderArtSet()->getSlot(slot);
}
void ChangeStackCount::applyGs(CGameState * gs)
{
auto * srcObj = gs->getArmyInstance(army);
@ -1709,41 +1648,43 @@ void RebalanceStacks::applyGs(CGameState * gs)
if(srcCount == count) //moving whole stack
{
[[maybe_unused]] const CCreature *c = dst.army->getCreature(dst.slot);
const auto c = dst.army->getCreature(dst.slot);
if(c) //stack at dest -> merge
{
assert(c == srcType);
auto alHere = ArtifactLocation (src.getStack(), ArtifactPosition::CREATURE_SLOT);
auto alDest = ArtifactLocation (dst.getStack(), ArtifactPosition::CREATURE_SLOT);
auto * artHere = alHere.getArt();
auto * artDest = alDest.getArt();
if (artHere)
const auto srcHero = dynamic_cast<CGHeroInstance*>(src.army.get());
const auto dstHero = dynamic_cast<CGHeroInstance*>(dst.army.get());
auto srcLoc = ArtifactLocation(srcHero->id, ArtifactPosition::CREATURE_SLOT);
auto dstLoc = ArtifactLocation(dstHero->id, ArtifactPosition::CREATURE_SLOT);
// TODO set creature id !!!
/*if (auto artHere = srcLoc.getArt())
{
if (alDest.getArt())
if (dstLoc.getArt())
{
auto * hero = dynamic_cast<CGHeroInstance *>(src.army.get());
auto dstSlot = ArtifactUtils::getArtBackpackPosition(hero, alDest.getArt()->getTypeId());
if(hero && dstSlot != ArtifactPosition::PRE_FIRST)
auto dstSlot = ArtifactUtils::getArtBackpackPosition(srcHero, dstLoc.getArt()->getTypeId());
if(srcHero && dstSlot != ArtifactPosition::PRE_FIRST)
{
artDest->move (alDest, ArtifactLocation (hero, dstSlot));
dstLoc.getArt()->move (dstLoc, ArtifactLocation (srcHero, dstSlot));
}
//else - artifact cna be lost :/
else
{
EraseArtifact ea;
ea.al = alDest;
ea.al = dstLoc;
ea.applyGs(gs);
logNetwork->warn("Cannot move artifact! No free slots");
}
artHere->move (alHere, alDest);
artHere->move (srcLoc, dstLoc);
//TODO: choose from dialog
}
else //just move to the other slot before stack gets erased
{
artHere->move (alHere, alDest);
artHere->move (srcLoc, dstLoc);
}
}
}*/
if (stackExp)
{
ui64 totalExp = srcCount * src.army->getStackExperience(src.slot) + dst.army->getStackCount(dst.slot) * dst.army->getStackExperience(dst.slot);
@ -1811,53 +1752,57 @@ void BulkSmartRebalanceStacks::applyGs(CGameState * gs)
void PutArtifact::applyGs(CGameState *gs)
{
assert(art->canBePutAt(al));
// Ensure that artifact has been correctly added via NewArtifact pack
assert(vstd::contains(gs->map->artInstances, art));
assert(!art->getParentNodes().empty());
art->putAt(al);
auto hero = gs->getHero(al.artHolder);
assert(hero);
assert(art->canBePutAt(hero, al.slot));
art->putAt(*hero, al.slot);
}
void EraseArtifact::applyGs(CGameState *gs)
{
const auto * slot = al.getSlot();
const auto hero = gs->getHero(al.artHolder);
assert(hero);
const auto slot = hero->getSlot(al.slot);
if(slot->locked)
{
logGlobal->debug("Erasing locked artifact: %s", slot->artifact->artType->getNameTranslated());
DisassembledArtifact dis;
dis.al.artHolder = al.artHolder;
auto * aset = al.getHolderArtSet();
#ifndef NDEBUG
bool found = false;
#endif
for(auto& p : aset->artifactsWorn)
for(auto & slotInfo : hero->artifactsWorn)
{
auto art = p.second.artifact;
auto art = slotInfo.second.artifact;
if(art->isCombined() && art->isPart(slot->artifact))
{
dis.al.slot = aset->getArtPos(art);
#ifndef NDEBUG
found = true;
#endif
dis.al.slot = hero->getArtPos(art);
break;
}
}
assert(found && "Failed to determine the assembly this locked artifact belongs to");
logGlobal->debug("Found the corresponding assembly: %s", dis.al.getSlot()->artifact->artType->getNameTranslated());
assert((dis.al.slot != ArtifactPosition::PRE_FIRST) && "Failed to determine the assembly this locked artifact belongs to");
logGlobal->debug("Found the corresponding assembly: %s", hero->getArt(dis.al.slot)->artType->getNameTranslated());
dis.applyGs(gs);
}
else
{
logGlobal->debug("Erasing artifact %s", slot->artifact->artType->getNameTranslated());
}
al.removeArtifact();
auto art = hero->getArt(al.slot);
assert(art);
art->removeFrom(*hero, al.slot);
}
void MoveArtifact::applyGs(CGameState * gs)
{
CArtifactInstance * art = src.getArt();
auto srcHero = gs->getHero(src.artHolder);
auto dstHero = gs->getHero(dst.artHolder);
assert(srcHero);
assert(dstHero);
auto art = srcHero->getArt(src.slot);
assert(!ArtifactUtils::isSlotEquipment(dst.slot) || !dst.getArt());
art->move(src, dst);
art->move(*srcHero, src.slot, *dstHero, dst.slot);
}
void BulkMoveArtifacts::applyGs(CGameState * gs)
@ -1887,7 +1832,7 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
assert(slotInfo);
auto * art = const_cast<CArtifactInstance *>(slotInfo->getArt());
assert(art);
switch(operation)
/*switch(operation)
{
case EBulkArtsOp::BULK_MOVE:
const_cast<CArtifactInstance*>(art)->move(
@ -1901,7 +1846,7 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
break;
default:
break;
}
}*/
if(srcPos >= ArtifactPosition::BACKPACK_START)
{
@ -1932,15 +1877,16 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
void AssembledArtifact::applyGs(CGameState *gs)
{
CArtifactSet * artSet = al.getHolderArtSet();
const CArtifactInstance * transformedArt = al.getArt();
auto hero = gs->getHero(al.artHolder);
assert(hero);
const auto transformedArt = hero->getArt(al.slot);
assert(transformedArt);
assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(artSet, transformedArt->getTypeId()), [=](const CArtifact * art)->bool
assert(vstd::contains_if(ArtifactUtils::assemblyPossibilities(hero, transformedArt->getTypeId()), [=](const CArtifact * art)->bool
{
return art->getId() == builtArt->getId();
}));
const auto transformedArtSlot = artSet->getSlotByInstance(transformedArt);
const auto transformedArtSlot = hero->getSlotByInstance(transformedArt);
auto * combinedArt = new CArtifactInstance(builtArt);
gs->map->addNewArtifactInstance(combinedArt);
@ -1952,7 +1898,7 @@ void AssembledArtifact::applyGs(CGameState *gs)
if(transformedArt->getTypeId() == constituent->getId())
slot = transformedArtSlot;
else
slot = artSet->getArtPos(constituent->getId(), false, false);
slot = hero->getArtPos(constituent->getId(), false, false);
assert(slot != ArtifactPosition::PRE_FIRST);
slotsInvolved.emplace_back(slot);
@ -1972,8 +1918,8 @@ void AssembledArtifact::applyGs(CGameState *gs)
break;
}
if(!vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), al.slot)
&& vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), slot))
if(!vstd::contains(combinedArt->artType->getPossibleSlots().at(hero->bearerType()), al.slot)
&& vstd::contains(combinedArt->artType->getPossibleSlots().at(hero->bearerType()), slot))
al.slot = slot;
}
else
@ -1986,8 +1932,8 @@ void AssembledArtifact::applyGs(CGameState *gs)
// Delete parts from hero
for(const auto slot : slotsInvolved)
{
const auto constituentInstance = artSet->getArt(slot);
constituentInstance->removeFrom(ArtifactLocation(al.artHolder, slot));
const auto constituentInstance = hero->getArt(slot);
constituentInstance->removeFrom(*hero, slot);
if(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot)
combinedArt->addPart(constituentInstance, slot);
@ -1996,25 +1942,26 @@ void AssembledArtifact::applyGs(CGameState *gs)
}
// Put new combined artifacts
combinedArt->putAt(al);
combinedArt->putAt(*hero, al.slot);
}
void DisassembledArtifact::applyGs(CGameState *gs)
{
auto * disassembled = al.getArt();
assert(disassembled);
auto hero = gs->getHero(al.artHolder);
assert(hero);
auto disassembledArt = hero->getArt(al.slot);
assert(disassembledArt);
auto parts = disassembled->getPartsInfo();
disassembled->removeFrom(al);
auto parts = disassembledArt->getPartsInfo();
disassembledArt->removeFrom(*hero, al.slot);
for(auto & part : parts)
{
ArtifactLocation partLoc = al;
// ArtifactPosition::PRE_FIRST is value of main part slot -> it'll replace combined artifact in its pos
partLoc.slot = (ArtifactUtils::isSlotEquipment(part.slot) ? part.slot : al.slot);
disassembled->detachFrom(*part.art);
part.art->putAt(partLoc);
auto slot = (ArtifactUtils::isSlotEquipment(part.slot) ? part.slot : al.slot);
disassembledArt->detachFrom(*part.art);
part.art->putAt(*hero, slot);
}
gs->map->eraseArtifactInstance(disassembled);
gs->map->eraseArtifactInstance(disassembledArt);
}
void HeroVisit::applyGs(CGameState *gs)

View File

@ -2270,7 +2270,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
if(!t->visitingHero || !t->visitingHero->hasArt(ArtifactID::GRAIL))
COMPLAIN_RET("Cannot build this without grail!")
else
removeArtifact(ArtifactLocation(t->visitingHero, t->visitingHero->getArtPos(ArtifactID::GRAIL, false)));
removeArtifact(ArtifactLocation(t->visitingHero->id, t->visitingHero->getArtPos(ArtifactID::GRAIL, false)));
}
break;
}
@ -2664,74 +2664,71 @@ 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 &al1, const ArtifactLocation &al2)
bool CGameHandler::moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst)
{
ArtifactLocation src = al1, dst = al2;
const PlayerColor srcPlayer = src.owningPlayer(), dstPlayer = dst.owningPlayer();
const CArmedInstance *srcObj = src.relatedObj(), *dstObj = dst.relatedObj();
const auto srcHero = getHero(src.artHolder), dstHero = getHero(dst.artHolder);
ArtifactLocation srcLoc = src, dstLoc = dst;
// Make sure exchange is even possible between the two heroes.
if(!isAllowedExchange(srcObj->id, dstObj->id))
if(!isAllowedExchange(srcLoc.artHolder, dstLoc.artHolder))
COMPLAIN_RET("That heroes cannot make any exchange!");
const CArtifactInstance *srcArtifact = src.getArt();
const CArtifactInstance *destArtifact = dst.getArt();
const bool isDstSlotBackpack = ArtifactUtils::isSlotBackpack(dst.slot);
const auto srcArtifact = srcHero->getArt(srcLoc.slot);
const auto dstArtifact = dstHero->getArt(dstLoc.slot);
const bool isDstSlotBackpack = ArtifactUtils::isSlotBackpack(dstLoc.slot);
if(srcArtifact == nullptr)
COMPLAIN_RET("No artifact to move!");
if(destArtifact && srcPlayer != dstPlayer && !isDstSlotBackpack)
if(dstArtifact && srcHero->getOwner() != dstHero->getOwner() && !isDstSlotBackpack)
COMPLAIN_RET("Can't touch artifact on hero of another player!");
// Check if src/dest slots are appropriate for the artifacts exchanged.
// Moving to the backpack is always allowed.
if((!srcArtifact || !isDstSlotBackpack)
&& srcArtifact && !srcArtifact->canBePutAt(dst, true))
if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstHero, dstLoc.slot, true))
COMPLAIN_RET("Cannot move artifact!");
auto srcSlot = src.getSlot();
auto dstSlot = dst.getSlot();
auto srcSlotInfo = srcHero->getSlot(srcLoc.slot);
auto dstSlotInfo = dstHero->getSlot(dstLoc.slot);
if((srcSlot && srcSlot->locked) || (dstSlot && dstSlot->locked))
if((srcSlotInfo && srcSlotInfo->locked) || (dstSlotInfo && dstSlotInfo->locked))
COMPLAIN_RET("Cannot move artifact locks.");
if(isDstSlotBackpack && srcArtifact->artType->isBig())
COMPLAIN_RET("Cannot put big artifacts in backpack!");
if(src.slot == ArtifactPosition::MACH4 || dst.slot == ArtifactPosition::MACH4)
if(srcLoc.slot == ArtifactPosition::MACH4 || dstLoc.slot == ArtifactPosition::MACH4)
COMPLAIN_RET("Cannot move catapult!");
if(isDstSlotBackpack)
{
if(!ArtifactUtils::isBackpackFreeSlots(dst.getHolderArtSet()))
if(!ArtifactUtils::isBackpackFreeSlots(dstHero))
COMPLAIN_RET("Backpack is full!");
vstd::amin(dst.slot, ArtifactPosition::BACKPACK_START + dst.getHolderArtSet()->artifactsInBackpack.size());
vstd::amin(dstLoc.slot, ArtifactPosition::BACKPACK_START + dstHero->artifactsInBackpack.size());
}
if(!(src.slot == ArtifactPosition::TRANSITION_POS && dst.slot == ArtifactPosition::TRANSITION_POS))
if(!(srcLoc.slot == ArtifactPosition::TRANSITION_POS && dstLoc.slot == ArtifactPosition::TRANSITION_POS))
{
if(src.slot == dst.slot && src.artHolder == dst.artHolder)
if(srcLoc.slot == dstLoc.slot && srcLoc.artHolder == dstLoc.artHolder)
COMPLAIN_RET("Won't move artifact: Dest same as source!");
// Check if dst slot is occupied
if(!isDstSlotBackpack && destArtifact)
if(!isDstSlotBackpack && dstArtifact)
{
// Previous artifact must be removed first
moveArtifact(dst, ArtifactLocation(dst.artHolder, ArtifactPosition::TRANSITION_POS));
moveArtifact(dstLoc, ArtifactLocation(dstLoc.artHolder, ArtifactPosition::TRANSITION_POS));
}
try
{
auto hero = std::get<ConstTransitivePtr<CGHeroInstance>>(dst.artHolder);
if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dst.slot))
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
if(ArtifactUtils::checkSpellbookIsNeeded(dstHero, srcArtifact->artType->getId(), dstLoc.slot))
giveHeroNewArtifact(dstHero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
}
catch(const std::bad_variant_access &)
{
// object other than hero received an art - ignore
}
MoveArtifact ma(&src, &dst);
if(src.artHolder == dst.artHolder)
MoveArtifact ma(&srcLoc, &dstLoc);
if(srcLoc.artHolder == dstLoc.artHolder)
ma.askAssemble = false;
sendAndApply(&ma);
}
@ -2854,7 +2851,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
if(!destArtifact)
COMPLAIN_RET("assembleArtifacts: there is no such artifact instance!");
const auto dstLoc = ArtifactLocation(hero, artifactSlot);
const auto dstLoc = ArtifactLocation(hero->id, artifactSlot);
if(assemble)
{
CArtifact * combinedArt = VLC->arth->objects[assembleTo];
@ -2864,8 +2861,8 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
{
COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!");
}
if(!destArtifact->canBePutAt(dstLoc)
&& !destArtifact->canBePutAt(ArtifactLocation(hero, ArtifactPosition::BACKPACK_START)))
if(!destArtifact->canBePutAt(hero, artifactSlot)
&& !destArtifact->canBePutAt(hero, ArtifactPosition::BACKPACK_START))
{
COMPLAIN_RET("assembleArtifacts: It's impossible to give the artholder requested artifact!");
}
@ -2897,15 +2894,15 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
bool CGameHandler::eraseArtifactByClient(const ArtifactLocation & al)
{
const auto * hero = getHero(al.relatedObj()->id);
const auto * hero = getHero(al.artHolder);
if(hero == nullptr)
COMPLAIN_RET("eraseArtifactByClient: wrong hero's ID");
const auto * art = al.getArt();
const auto * art = hero->getArt(al.slot);
if(art == nullptr)
COMPLAIN_RET("Cannot remove artifact!");
if(al.getArt()->artType->canBePutAt(hero) || al.slot != ArtifactPosition::TRANSITION_POS)
if(art->canBePutAt(hero) || al.slot != ArtifactPosition::TRANSITION_POS)
COMPLAIN_RET("Illegal artifact removal request");
removeArtifact(al);
@ -3012,7 +3009,7 @@ bool CGameHandler::sellArtifact(const IMarket *m, const CGHeroInstance *h, Artif
int resVal = 0, dump = 1;
m->getOffer(art->artType->getId(), rid, dump, resVal, EMarketMode::ARTIFACT_RESOURCE);
removeArtifact(ArtifactLocation(h, h->getArtPos(art)));
removeArtifact(ArtifactLocation(h->id, h->getArtPos(art)));
giveResource(h->tempOwner, rid, resVal);
return true;
}
@ -3750,8 +3747,8 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
for(int i = 0; i < slot.size(); ++i)
{
ArtifactLocation al(hero, slot[i]);
const CArtifactInstance * a = al.getArt();
ArtifactLocation al(hero->id, slot[i]);
const CArtifactInstance * a = hero->getArt(al.slot);
if(!a)
{
@ -3963,7 +3960,7 @@ bool CGameHandler::swapStacks(const StackLocation & sl1, const StackLocation & s
bool CGameHandler::giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos)
{
assert(a->artType);
ArtifactLocation al(h, ArtifactPosition::PRE_FIRST);
ArtifactLocation al(h->id, ArtifactPosition::PRE_FIRST);
if(pos == ArtifactPosition::FIRST_AVAILABLE)
{
@ -3978,7 +3975,7 @@ bool CGameHandler::giveHeroArtifact(const CGHeroInstance * h, const CArtifactIns
al.slot = pos;
}
if(a->canBePutAt(al))
if(a->canBePutAt(h, al.slot))
putArtifact(al, a);
else
return false;

View File

@ -130,7 +130,7 @@ public:
bool giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos) override;
void putArtifact(const ArtifactLocation &al, const CArtifactInstance *a) override;
void removeArtifact(const ArtifactLocation &al) override;
bool moveArtifact(const ArtifactLocation & al1, const ArtifactLocation & al2) override;
bool moveArtifact(const ArtifactLocation & src, const ArtifactLocation & dst) override;
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack);
bool eraseArtifactByClient(const ArtifactLocation & al);
void synchronizeArtifactHandlerLists();

View File

@ -134,7 +134,7 @@ void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & pack)
{
gh.throwIfWrongPlayer(&pack, pack.src.owningPlayer()); //second hero can be ally
gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.src.artHolder)); //second hero can be ally
result = gh.moveArtifact(pack.src, pack.dst);
}
@ -154,7 +154,7 @@ void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
void ApplyGhNetPackVisitor::visitEraseArtifactByClient(EraseArtifactByClient & pack)
{
gh.throwIfWrongPlayer(&pack, pack.al.owningPlayer());
gh.throwIfWrongPlayer(&pack, gh.getOwner(pack.al.artHolder));
result = gh.eraseArtifactByClient(pack.al);
}

View File

@ -79,7 +79,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CBattleInfoCallback & battle,
logGlobal->debug("War machine has been destroyed");
auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
if (hero)
removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
removedWarMachines.push_back (ArtifactLocation(hero->id, hero->getArtPos(warMachine, true)));
else
logGlobal->error("War machine in army without hero");
}
@ -339,7 +339,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
if(slot != ArtifactPosition::PRE_FIRST)
{
arts.push_back(art);
ma->dst = ArtifactLocation(finishingBattle->winnerHero, slot);
ma->dst = ArtifactLocation(finishingBattle->winnerHero->id, slot);
if(ArtifactUtils::isSlotBackpack(slot))
ma->askAssemble = false;
gameHandler->sendAndApply(ma);
@ -353,8 +353,8 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
for (auto artSlot : artifactsWorn)
{
MoveArtifact ma;
ma.src = ArtifactLocation(finishingBattle->loserHero, artSlot.first);
const CArtifactInstance * art = ma.src.getArt();
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
const CArtifactInstance * art = finishingBattle->loserHero->getArt(artSlot.first);
if (art && !art->artType->isBig() &&
art->artType->getId() != ArtifactID::SPELLBOOK)
// don't move war machines or locked arts (spellbook)
@ -366,9 +366,9 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
{
//we assume that no big artifacts can be found
MoveArtifact ma;
ma.src = ArtifactLocation(finishingBattle->loserHero,
ma.src = ArtifactLocation(finishingBattle->loserHero->id,
ArtifactPosition(ArtifactPosition::BACKPACK_START + slotNumber)); //backpack automatically shifts arts to beginning
const CArtifactInstance * art = ma.src.getArt();
const CArtifactInstance * art = finishingBattle->loserHero->getArt(ArtifactPosition::BACKPACK_START + slotNumber);
if (art->artType->getId() != ArtifactID::GRAIL) //grail may not be won
{
sendMoveArtifact(art, &ma);
@ -380,12 +380,13 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
for (auto artSlot : artifactsWorn)
{
MoveArtifact ma;
ma.src = ArtifactLocation(finishingBattle->loserHero->commander.get(), artSlot.first);
const CArtifactInstance * art = ma.src.getArt();
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
// TODO add ->commander.get() !!!
/*const CArtifactInstance* art = ma.src.getArt();
if (art && !art->artType->isBig())
{
sendMoveArtifact(art, &ma);
}
}*/
}
}
}
@ -395,16 +396,17 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
for (auto armySlot : battle.battleGetArmyObject(loser)->stacks)
{
auto artifactsWorn = armySlot.second->artifactsWorn;
for (auto artSlot : artifactsWorn)
/*for (auto artSlot : artifactsWorn)
{
MoveArtifact ma;
ma.src = ArtifactLocation(armySlot.second, artSlot.first);
const CArtifactInstance * art = ma.src.getArt();
const CArtifactInstance* art = ma.src.getArt();
if (art && !art->artType->isBig())
{
sendMoveArtifact(art, &ma);
}
}
// TODO add stack !!!
}*/
}
}

View File

@ -127,12 +127,12 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const
if(auto arts = dynamic_ptr_cast<ExchangeArtifacts>(pack))
{
if(auto id1 = std::visit(GetEngagedHeroIds(), arts->src.artHolder))
if(!vstd::contains(ourIds, *id1))
if(auto id1 = arts->src.artHolder)
if(!vstd::contains(ourIds, id1))
return true;
if(auto id2 = std::visit(GetEngagedHeroIds(), arts->dst.artHolder))
if(!vstd::contains(ourIds, *id2))
if(auto id2 = arts->dst.artHolder)
if(!vstd::contains(ourIds, id2))
return true;
return false;
}
@ -144,8 +144,8 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const
if(auto art = dynamic_ptr_cast<EraseArtifactByClient>(pack))
{
if (auto id = std::visit(GetEngagedHeroIds(), art->al.artHolder))
return !vstd::contains(ourIds, *id);
if(auto id = art->al.artHolder)
return !vstd::contains(ourIds, id);
}
if(auto dismiss = dynamic_ptr_cast<AssembleArtifacts>(pack))