mirror of
https://github.com/vcmi/vcmi.git
synced 2025-11-06 09:09:40 +02:00
Merge pull request #3069 from SoundSSGood/artifact-location-id
ArtifactLocation now use ID for artHolder identification
This commit is contained in:
@@ -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,65 +2664,66 @@ 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();
|
||||
ArtifactLocation srcLoc = src, dstLoc = dst;
|
||||
const auto srcArtSet = getArtSet(srcLoc);
|
||||
const auto dstArtSet = getArtSet(dstLoc);
|
||||
assert(srcArtSet);
|
||||
assert(dstArtSet);
|
||||
|
||||
// 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 = srcArtSet->getArt(srcLoc.slot);
|
||||
const auto dstArtifact = dstArtSet->getArt(dstLoc.slot);
|
||||
const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dstLoc.slot) : false;
|
||||
|
||||
if(srcArtifact == nullptr)
|
||||
COMPLAIN_RET("No artifact to move!");
|
||||
if(destArtifact && srcPlayer != dstPlayer && !isDstSlotBackpack)
|
||||
if(dstArtifact && getHero(src.artHolder)->getOwner() != getHero(dst.artHolder)->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(dstArtSet, dstLoc.slot, true))
|
||||
COMPLAIN_RET("Cannot move artifact!");
|
||||
|
||||
auto srcSlot = src.getSlot();
|
||||
auto dstSlot = dst.getSlot();
|
||||
auto srcSlotInfo = srcArtSet->getSlot(srcLoc.slot);
|
||||
auto dstSlotInfo = dstArtSet->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(dstArtSet))
|
||||
COMPLAIN_RET("Backpack is full!");
|
||||
vstd::amin(dst.slot, ArtifactPosition::BACKPACK_START + dst.getHolderArtSet()->artifactsInBackpack.size());
|
||||
vstd::amin(dstLoc.slot, ArtifactPosition::BACKPACK_START + dstArtSet->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))
|
||||
auto hero = getHero(dst.artHolder);
|
||||
if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dstLoc.slot))
|
||||
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||
}
|
||||
catch(const std::bad_variant_access &)
|
||||
@@ -2730,8 +2731,8 @@ bool CGameHandler::moveArtifact(const ArtifactLocation &al1, const ArtifactLocat
|
||||
// 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);
|
||||
}
|
||||
@@ -2749,8 +2750,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
|
||||
if((!psrcHero) || (!pdstHero))
|
||||
COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID");
|
||||
|
||||
BulkMoveArtifacts ma(static_cast<ConstTransitivePtr<CGHeroInstance>>(psrcHero),
|
||||
static_cast<ConstTransitivePtr<CGHeroInstance>>(pdstHero), swap);
|
||||
BulkMoveArtifacts ma(srcHero, dstHero, swap);
|
||||
auto & slotsSrcDst = ma.artsPack0;
|
||||
auto & slotsDstSrc = ma.artsPack1;
|
||||
|
||||
@@ -2854,7 +2854,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 +2864,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 +2897,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 +3012,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 +3750,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 +3963,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 +3978,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;
|
||||
|
||||
@@ -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();
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
|
||||
@@ -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,8 +380,9 @@ 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);
|
||||
ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
|
||||
const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
|
||||
if (art && !art->artType->isBig())
|
||||
{
|
||||
sendMoveArtifact(art, &ma);
|
||||
@@ -395,11 +396,12 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
||||
for (auto armySlot : battle.battleGetArmyObject(loser)->stacks)
|
||||
{
|
||||
auto artifactsWorn = armySlot.second->artifactsWorn;
|
||||
for (auto artSlot : artifactsWorn)
|
||||
for(const auto & artSlot : artifactsWorn)
|
||||
{
|
||||
MoveArtifact ma;
|
||||
ma.src = ArtifactLocation(armySlot.second, artSlot.first);
|
||||
const CArtifactInstance * art = ma.src.getArt();
|
||||
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
|
||||
ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
|
||||
const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
|
||||
if (art && !art->artType->isBig())
|
||||
{
|
||||
sendMoveArtifact(art, &ma);
|
||||
|
||||
@@ -17,20 +17,6 @@
|
||||
#include "../../lib/networkPacks/PacksForServer.h"
|
||||
#include "../../lib/serializer/Cast.h"
|
||||
|
||||
struct GetEngagedHeroIds
|
||||
{
|
||||
std::optional<ObjectInstanceID> operator()(const ConstTransitivePtr<CGHeroInstance> & h) const
|
||||
{
|
||||
return h->id;
|
||||
}
|
||||
std::optional<ObjectInstanceID> operator()(const ConstTransitivePtr<CStackInstance> & s) const
|
||||
{
|
||||
if(s->armyObj && s->armyObj->ID == Obj::HERO)
|
||||
return s->armyObj->id;
|
||||
return std::optional<ObjectInstanceID>();
|
||||
}
|
||||
};
|
||||
|
||||
TimerPauseQuery::TimerPauseQuery(CGameHandler * owner, PlayerColor player):
|
||||
CQuery(owner)
|
||||
{
|
||||
@@ -127,12 +113,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 +130,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))
|
||||
|
||||
Reference in New Issue
Block a user