mirror of
https://github.com/vcmi/vcmi.git
synced 2025-06-17 00:07:41 +02:00
Merge pull request #3069 from SoundSSGood/artifact-location-id
ArtifactLocation now use ID for artHolder identification
This commit is contained in:
@ -9,6 +9,7 @@
|
|||||||
*/
|
*/
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
|
|
||||||
|
#include "../../lib/ArtifactUtils.h"
|
||||||
#include "../../lib/UnlockGuard.h"
|
#include "../../lib/UnlockGuard.h"
|
||||||
#include "../../lib/mapObjects/MapObjects.h"
|
#include "../../lib/mapObjects/MapObjects.h"
|
||||||
#include "../../lib/mapObjects/ObjectTemplate.h"
|
#include "../../lib/mapObjects/ObjectTemplate.h"
|
||||||
@ -995,21 +996,21 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
|
|||||||
for(auto p : h->artifactsWorn)
|
for(auto p : h->artifactsWorn)
|
||||||
{
|
{
|
||||||
if(p.second.artifact)
|
if(p.second.artifact)
|
||||||
allArtifacts.push_back(ArtifactLocation(h, p.first));
|
allArtifacts.push_back(ArtifactLocation(h->id, p.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(auto slot : h->artifactsInBackpack)
|
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)
|
if(otherh)
|
||||||
{
|
{
|
||||||
for(auto p : otherh->artifactsWorn)
|
for(auto p : otherh->artifactsWorn)
|
||||||
{
|
{
|
||||||
if(p.second.artifact)
|
if(p.second.artifact)
|
||||||
allArtifacts.push_back(ArtifactLocation(otherh, p.first));
|
allArtifacts.push_back(ArtifactLocation(otherh->id, p.first));
|
||||||
}
|
}
|
||||||
for(auto slot : otherh->artifactsInBackpack)
|
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
|
//we give stuff to one hero or another, depending on giveStuffToFirstHero
|
||||||
|
|
||||||
@ -1021,13 +1022,13 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
|
|||||||
|
|
||||||
for(auto location : allArtifacts)
|
for(auto location : allArtifacts)
|
||||||
{
|
{
|
||||||
if(location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST)
|
if(location.artHolder == target->id && ArtifactUtils::isSlotEquipment(location.slot))
|
||||||
continue; //don't reequip artifact we already wear
|
continue; //don't reequip artifact we already wear
|
||||||
|
|
||||||
if(location.slot == ArtifactPosition::MACH4) // don't attempt to move catapult
|
if(location.slot == ArtifactPosition::MACH4) // don't attempt to move catapult
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto s = location.getSlot();
|
auto s = cb->getHero(location.artHolder)->getSlot(location.slot);
|
||||||
if(!s || s->locked) //we can't move locks
|
if(!s || s->locked) //we can't move locks
|
||||||
continue;
|
continue;
|
||||||
auto artifact = s->artifact;
|
auto artifact = s->artifact;
|
||||||
@ -1038,9 +1039,9 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
|
|||||||
bool emptySlotFound = false;
|
bool emptySlotFound = false;
|
||||||
for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType()))
|
for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType()))
|
||||||
{
|
{
|
||||||
ArtifactLocation destLocation(target, slot);
|
if(target->isPositionFree(slot) && artifact->canBePutAt(target, slot, true)) //combined artifacts are not always allowed to move
|
||||||
if(target->isPositionFree(slot) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move
|
|
||||||
{
|
{
|
||||||
|
ArtifactLocation destLocation(target->id, slot);
|
||||||
cb->swapArtifacts(location, destLocation); //just put into empty slot
|
cb->swapArtifacts(location, destLocation); //just put into empty slot
|
||||||
emptySlotFound = true;
|
emptySlotFound = true;
|
||||||
changeMade = true;
|
changeMade = true;
|
||||||
@ -1054,11 +1055,11 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance
|
|||||||
auto otherSlot = target->getSlot(slot);
|
auto otherSlot = target->getSlot(slot);
|
||||||
if(otherSlot && otherSlot->artifact) //we need to exchange artifact for better one
|
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 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;
|
changeMade = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -14,6 +14,7 @@
|
|||||||
#include "BuildingManager.h"
|
#include "BuildingManager.h"
|
||||||
#include "Goals/Goals.h"
|
#include "Goals/Goals.h"
|
||||||
|
|
||||||
|
#include "../../lib/ArtifactUtils.h"
|
||||||
#include "../../lib/UnlockGuard.h"
|
#include "../../lib/UnlockGuard.h"
|
||||||
#include "../../lib/mapObjects/MapObjects.h"
|
#include "../../lib/mapObjects/MapObjects.h"
|
||||||
#include "../../lib/mapObjects/ObjectTemplate.h"
|
#include "../../lib/mapObjects/ObjectTemplate.h"
|
||||||
@ -1166,21 +1167,21 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
|
|||||||
for(auto p : h->artifactsWorn)
|
for(auto p : h->artifactsWorn)
|
||||||
{
|
{
|
||||||
if(p.second.artifact)
|
if(p.second.artifact)
|
||||||
allArtifacts.push_back(ArtifactLocation(h, p.first));
|
allArtifacts.push_back(ArtifactLocation(h->id, p.first));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for(auto slot : h->artifactsInBackpack)
|
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)
|
if(otherh)
|
||||||
{
|
{
|
||||||
for(auto p : otherh->artifactsWorn)
|
for(auto p : otherh->artifactsWorn)
|
||||||
{
|
{
|
||||||
if(p.second.artifact)
|
if(p.second.artifact)
|
||||||
allArtifacts.push_back(ArtifactLocation(otherh, p.first));
|
allArtifacts.push_back(ArtifactLocation(otherh->id, p.first));
|
||||||
}
|
}
|
||||||
for(auto slot : otherh->artifactsInBackpack)
|
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
|
//we give stuff to one hero or another, depending on giveStuffToFirstHero
|
||||||
|
|
||||||
@ -1195,10 +1196,10 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
|
|||||||
if(location.slot == ArtifactPosition::MACH4 || location.slot == ArtifactPosition::SPELLBOOK)
|
if(location.slot == ArtifactPosition::MACH4 || location.slot == ArtifactPosition::SPELLBOOK)
|
||||||
continue; // don't attempt to move catapult and spellbook
|
continue; // don't attempt to move catapult and spellbook
|
||||||
|
|
||||||
if(location.relatedObj() == target && location.slot < ArtifactPosition::AFTER_LAST)
|
if(location.artHolder == target->id && ArtifactUtils::isSlotEquipment(location.slot))
|
||||||
continue; //don't reequip artifact we already wear
|
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
|
if(!s || s->locked) //we can't move locks
|
||||||
continue;
|
continue;
|
||||||
auto artifact = s->artifact;
|
auto artifact = s->artifact;
|
||||||
@ -1209,9 +1210,9 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
|
|||||||
bool emptySlotFound = false;
|
bool emptySlotFound = false;
|
||||||
for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType()))
|
for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType()))
|
||||||
{
|
{
|
||||||
ArtifactLocation destLocation(target, slot);
|
if(target->isPositionFree(slot) && artifact->canBePutAt(target, slot, true)) //combined artifacts are not always allowed to move
|
||||||
if(target->isPositionFree(slot) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move
|
|
||||||
{
|
{
|
||||||
|
ArtifactLocation destLocation(target->id, slot);
|
||||||
cb->swapArtifacts(location, destLocation); //just put into empty slot
|
cb->swapArtifacts(location, destLocation); //just put into empty slot
|
||||||
emptySlotFound = true;
|
emptySlotFound = true;
|
||||||
changeMade = true;
|
changeMade = true;
|
||||||
@ -1225,11 +1226,11 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot
|
|||||||
auto otherSlot = target->getSlot(slot);
|
auto otherSlot = target->getSlot(slot);
|
||||||
if(otherSlot && otherSlot->artifact) //we need to exchange artifact for better one
|
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 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;
|
changeMade = true;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -1753,8 +1753,7 @@ void CPlayerInterface::requestReturningToMainMenu(bool won)
|
|||||||
|
|
||||||
void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
|
void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
|
||||||
{
|
{
|
||||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
if(auto hero = cb->getHero(al.artHolder))
|
||||||
if(hero)
|
|
||||||
{
|
{
|
||||||
auto art = hero->getArt(al.slot);
|
auto art = hero->getArt(al.slot);
|
||||||
if(art == nullptr)
|
if(art == nullptr)
|
||||||
@ -1770,15 +1769,13 @@ void CPlayerInterface::askToAssembleArtifact(const ArtifactLocation &al)
|
|||||||
void CPlayerInterface::artifactPut(const ArtifactLocation &al)
|
void CPlayerInterface::artifactPut(const ArtifactLocation &al)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
|
||||||
adventureInt->onHeroChanged(hero);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
|
||||||
adventureInt->onHeroChanged(hero);
|
|
||||||
|
|
||||||
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
|
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
|
||||||
artWin->artifactRemoved(al);
|
artWin->artifactRemoved(al);
|
||||||
@ -1789,8 +1786,7 @@ void CPlayerInterface::artifactRemoved(const ArtifactLocation &al)
|
|||||||
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
|
void CPlayerInterface::artifactMoved(const ArtifactLocation &src, const ArtifactLocation &dst)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
auto hero = std::visit(HeroObjectRetriever(), dst.artHolder);
|
adventureInt->onHeroChanged(cb->getHero(dst.artHolder));
|
||||||
adventureInt->onHeroChanged(hero);
|
|
||||||
|
|
||||||
bool redraw = true;
|
bool redraw = true;
|
||||||
// If a bulk transfer has arrived, then redrawing only the last art movement.
|
// 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)
|
void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
|
||||||
adventureInt->onHeroChanged(hero);
|
|
||||||
|
|
||||||
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
|
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
|
||||||
artWin->artifactAssembled(al);
|
artWin->artifactAssembled(al);
|
||||||
@ -1825,8 +1820,7 @@ void CPlayerInterface::artifactAssembled(const ArtifactLocation &al)
|
|||||||
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
void CPlayerInterface::artifactDisassembled(const ArtifactLocation &al)
|
||||||
{
|
{
|
||||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||||
auto hero = std::visit(HeroObjectRetriever(), al.artHolder);
|
adventureInt->onHeroChanged(cb->getHero(al.artHolder));
|
||||||
adventureInt->onHeroChanged(hero);
|
|
||||||
|
|
||||||
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
|
for(auto artWin : GH.windows().findWindows<CArtifactHolder>())
|
||||||
artWin->artifactDisassembled(al);
|
artWin->artifactDisassembled(al);
|
||||||
|
@ -267,14 +267,14 @@ void ApplyClientNetPackVisitor::visitBulkSmartRebalanceStacks(BulkSmartRebalance
|
|||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitPutArtifact(PutArtifact & pack)
|
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)
|
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)
|
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)
|
void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack)
|
||||||
@ -286,9 +286,9 @@ void ApplyClientNetPackVisitor::visitMoveArtifact(MoveArtifact & pack)
|
|||||||
callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst);
|
callInterfaceIfPresent(cl, player, &IGameEventsReceiver::askToAssembleArtifact, pack.dst);
|
||||||
};
|
};
|
||||||
|
|
||||||
moveArtifact(pack.src.owningPlayer());
|
moveArtifact(cl.getOwner(pack.src.artHolder));
|
||||||
if(pack.src.owningPlayer() != pack.dst.owningPlayer())
|
if(cl.getOwner(pack.src.artHolder) != cl.getOwner(pack.dst.artHolder))
|
||||||
moveArtifact(pack.dst.owningPlayer());
|
moveArtifact(cl.getOwner(pack.dst.artHolder));
|
||||||
|
|
||||||
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
||||||
}
|
}
|
||||||
@ -306,8 +306,8 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
auto srcOwner = std::get<ConstTransitivePtr<CGHeroInstance>>(pack.srcArtHolder)->tempOwner;
|
auto srcOwner = cl.getOwner(pack.srcArtHolder);
|
||||||
auto dstOwner = std::get<ConstTransitivePtr<CGHeroInstance>>(pack.dstArtHolder)->tempOwner;
|
auto dstOwner = cl.getOwner(pack.dstArtHolder);
|
||||||
|
|
||||||
// Begin a session of bulk movement of arts. It is not necessary but useful for the client optimization.
|
// Begin a session of bulk movement of arts. It is not necessary but useful for the client optimization.
|
||||||
callInterfaceIfPresent(cl, srcOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size());
|
callInterfaceIfPresent(cl, srcOwner, &IGameEventsReceiver::bulkArtMovementStart, pack.artsPack0.size() + pack.artsPack1.size());
|
||||||
@ -321,14 +321,14 @@ void ApplyClientNetPackVisitor::visitBulkMoveArtifacts(BulkMoveArtifacts & pack)
|
|||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitAssembledArtifact(AssembledArtifact & pack)
|
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
|
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
||||||
}
|
}
|
||||||
|
|
||||||
void ApplyClientNetPackVisitor::visitDisassembledArtifact(DisassembledArtifact & pack)
|
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
|
cl.invalidatePaths(); // hero might have equipped/unequipped Angel Wings
|
||||||
}
|
}
|
||||||
|
@ -121,10 +121,11 @@ void CCommanderArtPlace::returnArtToHeroCallback()
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
ArtifactLocation src(commanderOwner->commander.get(), artifactPos);
|
ArtifactLocation src(commanderOwner->id, artifactPos);
|
||||||
ArtifactLocation dst(commanderOwner, freeSlot);
|
src.creature = SlotID::COMMANDER_SLOT_PLACEHOLDER;
|
||||||
|
ArtifactLocation dst(commanderOwner->id, freeSlot);
|
||||||
|
|
||||||
if(ourArt->canBePutAt(dst, true))
|
if(ourArt->canBePutAt(commanderOwner, freeSlot, true))
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->swapArtifacts(src, dst);
|
LOCPLINT->cb->swapArtifacts(src, dst);
|
||||||
setArtifact(nullptr);
|
setArtifact(nullptr);
|
||||||
|
@ -72,7 +72,7 @@ void CArtifactsOfHeroAltar::pickUpArtifact(CHeroArtPlace & artPlace)
|
|||||||
if(ArtifactUtils::isSlotBackpack(pickedArtFromSlot))
|
if(ArtifactUtils::isSlotBackpack(pickedArtFromSlot))
|
||||||
pickedArtFromSlot = curHero->getSlotByInstance(art);
|
pickedArtFromSlot = curHero->getSlotByInstance(art);
|
||||||
assert(pickedArtFromSlot != ArtifactPosition::PRE_FIRST);
|
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)
|
if(ArtifactUtils::isSlotBackpack(slot) || ArtifactUtils::isSlotEquipment(slot) || slot == ArtifactPosition::TRANSITION_POS)
|
||||||
{
|
{
|
||||||
assert(curHero->getSlot(slot)->getArt());
|
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;
|
pickedArtFromSlot = ArtifactPosition::PRE_FIRST;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -80,8 +80,8 @@ void CArtifactsOfHeroBackpack::swapArtifacts(const ArtifactLocation & srcLoc, co
|
|||||||
|
|
||||||
void CArtifactsOfHeroBackpack::pickUpArtifact(CHeroArtPlace & artPlace)
|
void CArtifactsOfHeroBackpack::pickUpArtifact(CHeroArtPlace & artPlace)
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, artPlace.slot),
|
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot),
|
||||||
ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
|
ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CArtifactsOfHeroBackpack::scrollBackpack(int offset)
|
void CArtifactsOfHeroBackpack::scrollBackpack(int offset)
|
||||||
|
@ -39,11 +39,11 @@ void CArtifactsOfHeroBase::putBackPickedArtifact()
|
|||||||
auto slot = ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->getTypeId());
|
auto slot = ArtifactUtils::getArtAnyPosition(curHero, curHero->artifactsTransitionPos.begin()->artifact->getTypeId());
|
||||||
if(slot == ArtifactPosition::PRE_FIRST)
|
if(slot == ArtifactPosition::PRE_FIRST)
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
|
LOCPLINT->cb->eraseArtifactByClient(ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
|
||||||
}
|
}
|
||||||
else
|
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)
|
if(putBackPickedArtCallback)
|
||||||
@ -178,7 +178,7 @@ void CArtifactsOfHeroBase::scrollBackpackForArtSet(int offset, const CArtifactSe
|
|||||||
void CArtifactsOfHeroBase::markPossibleSlots(const CArtifactInstance * art, bool assumeDestRemoved)
|
void CArtifactsOfHeroBase::markPossibleSlots(const CArtifactInstance * art, bool assumeDestRemoved)
|
||||||
{
|
{
|
||||||
for(auto artPlace : artWorn)
|
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()
|
void CArtifactsOfHeroBase::unmarkSlots()
|
||||||
|
@ -13,6 +13,7 @@
|
|||||||
#include "Buttons.h"
|
#include "Buttons.h"
|
||||||
|
|
||||||
#include "../CPlayerInterface.h"
|
#include "../CPlayerInterface.h"
|
||||||
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
|
||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
#include "../../lib/networkPacks/ArtifactLocation.h"
|
#include "../../lib/networkPacks/ArtifactLocation.h"
|
||||||
@ -56,7 +57,7 @@ void CArtifactsOfHeroKingdom::swapArtifacts(const ArtifactLocation & srcLoc, con
|
|||||||
|
|
||||||
void CArtifactsOfHeroKingdom::pickUpArtifact(CHeroArtPlace & artPlace)
|
void CArtifactsOfHeroKingdom::pickUpArtifact(CHeroArtPlace & artPlace)
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, artPlace.slot),
|
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot),
|
||||||
ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
|
ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -11,6 +11,7 @@
|
|||||||
#include "CArtifactsOfHeroMain.h"
|
#include "CArtifactsOfHeroMain.h"
|
||||||
|
|
||||||
#include "../CPlayerInterface.h"
|
#include "../CPlayerInterface.h"
|
||||||
|
#include "../../lib/mapObjects/CGHeroInstance.h"
|
||||||
|
|
||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
#include "../../lib/networkPacks/ArtifactLocation.h"
|
#include "../../lib/networkPacks/ArtifactLocation.h"
|
||||||
@ -36,6 +37,6 @@ void CArtifactsOfHeroMain::swapArtifacts(const ArtifactLocation & srcLoc, const
|
|||||||
|
|
||||||
void CArtifactsOfHeroMain::pickUpArtifact(CHeroArtPlace & artPlace)
|
void CArtifactsOfHeroMain::pickUpArtifact(CHeroArtPlace & artPlace)
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero, artPlace.slot),
|
LOCPLINT->cb->swapArtifacts(ArtifactLocation(curHero->id, artPlace.slot),
|
||||||
ArtifactLocation(curHero, ArtifactPosition::TRANSITION_POS));
|
ArtifactLocation(curHero->id, ArtifactPosition::TRANSITION_POS));
|
||||||
}
|
}
|
||||||
|
@ -196,16 +196,18 @@ bool CGarrisonSlot::highlightOrDropArtifact()
|
|||||||
artSelected = true;
|
artSelected = true;
|
||||||
if (myStack) // try dropping the artifact only if the slot isn't empty
|
if (myStack) // try dropping the artifact only if the slot isn't empty
|
||||||
{
|
{
|
||||||
ArtifactLocation src(srcHero, ArtifactPosition::TRANSITION_POS);
|
ArtifactLocation src(srcHero->id, ArtifactPosition::TRANSITION_POS);
|
||||||
ArtifactLocation dst(myStack, ArtifactPosition::CREATURE_SLOT);
|
ArtifactLocation dst(getObj()->id, ArtifactPosition::CREATURE_SLOT);
|
||||||
if(pickedArtInst->canBePutAt(dst, true))
|
dst.creature = getSlot();
|
||||||
|
|
||||||
|
if(pickedArtInst->canBePutAt(myStack, ArtifactPosition::CREATURE_SLOT, true))
|
||||||
{ //equip clicked stack
|
{ //equip clicked stack
|
||||||
if(dst.getArt())
|
if(auto dstArt = myStack->getArt(ArtifactPosition::CREATURE_SLOT))
|
||||||
{
|
{
|
||||||
//creature can wear only one active artifact
|
//creature can wear only one active artifact
|
||||||
//if we are placing a new one, the old one will be returned to the hero's backpack
|
//if we are placing a new one, the old one will be returned to the hero's backpack
|
||||||
LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero,
|
LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(srcHero->id,
|
||||||
ArtifactUtils::getArtBackpackPosition(srcHero, dst.getArt()->getTypeId())));
|
ArtifactUtils::getArtBackpackPosition(srcHero, dstArt->getTypeId())));
|
||||||
}
|
}
|
||||||
LOCPLINT->cb->swapArtifacts(src, dst);
|
LOCPLINT->cb->swapArtifacts(src, dst);
|
||||||
}
|
}
|
||||||
|
@ -122,8 +122,8 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst
|
|||||||
|
|
||||||
if(pickedArtInst)
|
if(pickedArtInst)
|
||||||
{
|
{
|
||||||
auto srcLoc = ArtifactLocation(heroPickedArt, ArtifactPosition::TRANSITION_POS);
|
auto srcLoc = ArtifactLocation(heroPickedArt->id, ArtifactPosition::TRANSITION_POS);
|
||||||
auto dstLoc = ArtifactLocation(hero, artPlace.slot);
|
auto dstLoc = ArtifactLocation(hero->id, artPlace.slot);
|
||||||
|
|
||||||
if(ArtifactUtils::isSlotBackpack(artPlace.slot))
|
if(ArtifactUtils::isSlotBackpack(artPlace.slot))
|
||||||
{
|
{
|
||||||
@ -141,7 +141,7 @@ void CWindowWithArtifacts::leftClickArtPlaceHero(CArtifactsOfHeroBase & artsInst
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Check if artifact transfer is possible
|
// 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;
|
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.
|
// we have a different artifact may look surprising... but it's valid.
|
||||||
|
|
||||||
auto pickedArtInst = std::get<const CArtifactInstance*>(curState.value());
|
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
|
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
|
// 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))
|
if(auto artPlace = artSetPtr->getArtPlace(destLoc.slot))
|
||||||
artPlace->hover(true);
|
artPlace->hover(true);
|
||||||
|
@ -974,11 +974,12 @@ void CStackWindow::removeStackArtifact(ArtifactPosition pos)
|
|||||||
const auto slot = ArtifactUtils::getArtBackpackPosition(info->owner, art->getTypeId());
|
const auto slot = ArtifactUtils::getArtBackpackPosition(info->owner, art->getTypeId());
|
||||||
if(slot != ArtifactPosition::PRE_FIRST)
|
if(slot != ArtifactPosition::PRE_FIRST)
|
||||||
{
|
{
|
||||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(info->stackNode, pos), ArtifactLocation(info->owner, slot));
|
auto artLoc = ArtifactLocation(info->owner->id, pos);
|
||||||
|
artLoc.creature = info->stackNode->armyObj->findStack(info->stackNode);
|
||||||
|
LOCPLINT->cb->swapArtifacts(artLoc, ArtifactLocation(info->owner->id, slot));
|
||||||
stackArtifactButton.reset();
|
stackArtifactButton.reset();
|
||||||
stackArtifactHelp.reset();
|
stackArtifactHelp.reset();
|
||||||
stackArtifactIcon.reset();
|
stackArtifactIcon.reset();
|
||||||
redraw();
|
redraw();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -334,20 +334,11 @@ void CHeroWindow::commanderWindow()
|
|||||||
if(pickedArtInst)
|
if(pickedArtInst)
|
||||||
{
|
{
|
||||||
const auto freeSlot = ArtifactUtils::getArtAnyPosition(curHero->commander, pickedArtInst->getTypeId());
|
const auto freeSlot = ArtifactUtils::getArtAnyPosition(curHero->commander, pickedArtInst->getTypeId());
|
||||||
if(freeSlot < ArtifactPosition::COMMANDER_AFTER_LAST) //we don't want to put it in commander's backpack!
|
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->id, freeSlot);
|
||||||
ArtifactLocation dst(curHero->commander.get(), freeSlot);
|
dst.creature = SlotID::COMMANDER_SLOT_PLACEHOLDER;
|
||||||
|
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS), dst);
|
||||||
if(pickedArtInst->canBePutAt(dst, true))
|
|
||||||
{ //equip clicked stack
|
|
||||||
if(dst.getArt())
|
|
||||||
{
|
|
||||||
LOCPLINT->cb->swapArtifacts(dst, ArtifactLocation(hero,
|
|
||||||
ArtifactUtils::getArtBackpackPosition(hero, pickedArtInst->getTypeId())));
|
|
||||||
}
|
|
||||||
LOCPLINT->cb->swapArtifacts(src, dst);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -191,8 +191,8 @@ void CTradeWindow::CTradeableItem::clickPressed(const Point & cursorPosition)
|
|||||||
const auto hero = aw->arts->getHero();
|
const auto hero = aw->arts->getHero();
|
||||||
const auto slot = hero->getSlotByInstance(art);
|
const auto slot = hero->getSlotByInstance(art);
|
||||||
assert(slot != ArtifactPosition::PRE_FIRST);
|
assert(slot != ArtifactPosition::PRE_FIRST);
|
||||||
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero, slot),
|
LOCPLINT->cb->swapArtifacts(ArtifactLocation(hero->id, slot),
|
||||||
ArtifactLocation(hero, ArtifactPosition::TRANSITION_POS));
|
ArtifactLocation(hero->id, ArtifactPosition::TRANSITION_POS));
|
||||||
aw->arts->pickedArtFromSlot = slot;
|
aw->arts->pickedArtFromSlot = slot;
|
||||||
aw->arts->artifactsOnAltar.erase(art);
|
aw->arts->artifactsOnAltar.erase(art);
|
||||||
setID(-1);
|
setID(-1);
|
||||||
|
@ -74,6 +74,49 @@ DLL_LINKAGE const std::vector<ArtifactPosition> & ArtifactUtils::constituentWorn
|
|||||||
return positions;
|
return positions;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
DLL_LINKAGE const std::vector<ArtifactPosition> & ArtifactUtils::allWornSlots()
|
||||||
|
{
|
||||||
|
static const std::vector<ArtifactPosition> positions =
|
||||||
|
{
|
||||||
|
ArtifactPosition::HEAD,
|
||||||
|
ArtifactPosition::SHOULDERS,
|
||||||
|
ArtifactPosition::NECK,
|
||||||
|
ArtifactPosition::RIGHT_HAND,
|
||||||
|
ArtifactPosition::LEFT_HAND,
|
||||||
|
ArtifactPosition::TORSO,
|
||||||
|
ArtifactPosition::RIGHT_RING,
|
||||||
|
ArtifactPosition::LEFT_RING,
|
||||||
|
ArtifactPosition::FEET,
|
||||||
|
ArtifactPosition::MISC1,
|
||||||
|
ArtifactPosition::MISC2,
|
||||||
|
ArtifactPosition::MISC3,
|
||||||
|
ArtifactPosition::MISC4,
|
||||||
|
ArtifactPosition::MISC5,
|
||||||
|
ArtifactPosition::MACH1,
|
||||||
|
ArtifactPosition::MACH2,
|
||||||
|
ArtifactPosition::MACH3,
|
||||||
|
ArtifactPosition::MACH4,
|
||||||
|
ArtifactPosition::SPELLBOOK
|
||||||
|
};
|
||||||
|
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
|
DLL_LINKAGE const std::vector<ArtifactPosition> & ArtifactUtils::commanderSlots()
|
||||||
|
{
|
||||||
|
static const std::vector<ArtifactPosition> positions =
|
||||||
|
{
|
||||||
|
ArtifactPosition::COMMANDER1,
|
||||||
|
ArtifactPosition::COMMANDER2,
|
||||||
|
ArtifactPosition::COMMANDER3,
|
||||||
|
ArtifactPosition::COMMANDER4,
|
||||||
|
ArtifactPosition::COMMANDER5,
|
||||||
|
ArtifactPosition::COMMANDER6
|
||||||
|
};
|
||||||
|
|
||||||
|
return positions;
|
||||||
|
}
|
||||||
|
|
||||||
DLL_LINKAGE bool ArtifactUtils::isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot)
|
DLL_LINKAGE bool ArtifactUtils::isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot)
|
||||||
{
|
{
|
||||||
return slot.second.artifact
|
return slot.second.artifact
|
||||||
|
@ -31,6 +31,8 @@ namespace ArtifactUtils
|
|||||||
// TODO: Make this constexpr when the toolset is upgraded
|
// TODO: Make this constexpr when the toolset is upgraded
|
||||||
DLL_LINKAGE const std::vector<ArtifactPosition> & unmovableSlots();
|
DLL_LINKAGE const std::vector<ArtifactPosition> & unmovableSlots();
|
||||||
DLL_LINKAGE const std::vector<ArtifactPosition> & constituentWornSlots();
|
DLL_LINKAGE const std::vector<ArtifactPosition> & constituentWornSlots();
|
||||||
|
DLL_LINKAGE const std::vector<ArtifactPosition> & allWornSlots();
|
||||||
|
DLL_LINKAGE const std::vector<ArtifactPosition> & commanderSlots();
|
||||||
DLL_LINKAGE bool isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot);
|
DLL_LINKAGE bool isArtRemovable(const std::pair<ArtifactPosition, ArtSlotInfo> & slot);
|
||||||
DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, const ArtifactID & artID, const ArtifactPosition & slot);
|
DLL_LINKAGE bool checkSpellbookIsNeeded(const CGHeroInstance * heroPtr, const ArtifactID & artID, const ArtifactPosition & slot);
|
||||||
DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot);
|
DLL_LINKAGE bool isSlotBackpack(const ArtifactPosition & slot);
|
||||||
|
@ -693,8 +693,8 @@ void CArtHandler::makeItCommanderArt(CArtifact * a, bool onlyCommander)
|
|||||||
a->possibleSlots[ArtBearer::HERO].clear();
|
a->possibleSlots[ArtBearer::HERO].clear();
|
||||||
a->possibleSlots[ArtBearer::CREATURE].clear();
|
a->possibleSlots[ArtBearer::CREATURE].clear();
|
||||||
}
|
}
|
||||||
for (int i = ArtifactPosition::COMMANDER1; i <= ArtifactPosition::COMMANDER6; ++i)
|
for(const auto & slot : ArtifactUtils::commanderSlots())
|
||||||
a->possibleSlots[ArtBearer::COMMANDER].push_back(ArtifactPosition(i));
|
a->possibleSlots[ArtBearer::COMMANDER].push_back(ArtifactPosition(slot));
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CArtHandler::legalArtifact(const ArtifactID & id)
|
bool CArtHandler::legalArtifact(const ArtifactID & id)
|
||||||
@ -975,9 +975,9 @@ const ArtSlotInfo * CArtifactSet::getSlot(const ArtifactPosition & pos) const
|
|||||||
}
|
}
|
||||||
if(vstd::contains(artifactsWorn, pos))
|
if(vstd::contains(artifactsWorn, pos))
|
||||||
return &artifactsWorn.at(pos);
|
return &artifactsWorn.at(pos);
|
||||||
if(pos >= ArtifactPosition::AFTER_LAST )
|
if(ArtifactUtils::isSlotBackpack(pos))
|
||||||
{
|
{
|
||||||
int backpackPos = (int)pos - ArtifactPosition::BACKPACK_START;
|
auto backpackPos = pos - ArtifactPosition::BACKPACK_START;
|
||||||
if(backpackPos < 0 || backpackPos >= artifactsInBackpack.size())
|
if(backpackPos < 0 || backpackPos >= artifactsInBackpack.size())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
else
|
else
|
||||||
@ -1080,9 +1080,9 @@ void CArtifactSet::serializeJsonArtifacts(JsonSerializeFormat & handler, const s
|
|||||||
|
|
||||||
void CArtifactSet::serializeJsonHero(JsonSerializeFormat & handler, CMap * map)
|
void CArtifactSet::serializeJsonHero(JsonSerializeFormat & handler, CMap * map)
|
||||||
{
|
{
|
||||||
for(ArtifactPosition ap = ArtifactPosition::HEAD; ap < ArtifactPosition::AFTER_LAST; ap.advance(1))
|
for(const auto & slot : ArtifactUtils::allWornSlots())
|
||||||
{
|
{
|
||||||
serializeJsonSlot(handler, ap, map);
|
serializeJsonSlot(handler, slot, map);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::vector<ArtifactID> backpackTemp;
|
std::vector<ArtifactID> backpackTemp;
|
||||||
|
@ -155,9 +155,9 @@ void CArtifactInstance::setId(ArtifactInstanceID id)
|
|||||||
this->id = 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
|
bool CArtifactInstance::isCombined() const
|
||||||
@ -165,15 +165,15 @@ bool CArtifactInstance::isCombined() const
|
|||||||
return artType->isCombined();
|
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);
|
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)
|
for(auto & part : partsInfo)
|
||||||
{
|
{
|
||||||
if(part.slot != ArtifactPosition::PRE_FIRST)
|
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);
|
removeFrom(srcSet, srcSlot);
|
||||||
putAt(dst);
|
putAt(dstSet, dstSlot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CArtifactInstance::deserializationFix()
|
void CArtifactInstance::deserializationFix()
|
||||||
|
@ -84,11 +84,12 @@ public:
|
|||||||
ArtifactInstanceID getId() const;
|
ArtifactInstanceID getId() const;
|
||||||
void setId(ArtifactInstanceID id);
|
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;
|
bool isCombined() const;
|
||||||
void putAt(const ArtifactLocation & al);
|
void putAt(CArtifactSet & set, const ArtifactPosition slot);
|
||||||
void removeFrom(const ArtifactLocation & al);
|
void removeFrom(CArtifactSet & set, const ArtifactPosition slot);
|
||||||
void move(const ArtifactLocation & src, const ArtifactLocation & dst);
|
void move(CArtifactSet & srcSet, const ArtifactPosition srcSlot, CArtifactSet & dstSet, const ArtifactPosition dstSlot);
|
||||||
|
|
||||||
void deserializationFix();
|
void deserializationFix();
|
||||||
template <typename Handler> void serialize(Handler & h, const int version)
|
template <typename Handler> void serialize(Handler & h, const int version)
|
||||||
|
@ -458,7 +458,7 @@ const CStackInstance & CCreatureSet::getStack(const SlotID & slot) const
|
|||||||
return *getStackPtr(slot);
|
return *getStackPtr(slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CStackInstance * CCreatureSet::getStackPtr(const SlotID & slot) const
|
CStackInstance * CCreatureSet::getStackPtr(const SlotID & slot) const
|
||||||
{
|
{
|
||||||
if(hasStackAtSlot(slot))
|
if(hasStackAtSlot(slot))
|
||||||
return stacks.find(slot)->second;
|
return stacks.find(slot)->second;
|
||||||
@ -870,7 +870,7 @@ ArtBearer::ArtBearer CStackInstance::bearerType() const
|
|||||||
CStackInstance::ArtPlacementMap 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->canBePutAt(this, pos));
|
||||||
|
|
||||||
attachTo(*art);
|
attachTo(*art);
|
||||||
return CArtifactSet::putArtifact(pos, art);
|
return CArtifactSet::putArtifact(pos, art);
|
||||||
|
@ -253,7 +253,7 @@ public:
|
|||||||
void setToArmy(CSimpleArmy &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
|
void setToArmy(CSimpleArmy &src); //erases all our army and moves stacks from src to us; src MUST NOT be an armed object! WARNING: use it wisely. Or better do not use at all.
|
||||||
|
|
||||||
const CStackInstance & getStack(const SlotID & slot) const; //stack must exist
|
const CStackInstance & getStack(const SlotID & slot) const; //stack must exist
|
||||||
const CStackInstance * getStackPtr(const SlotID & slot) const; //if stack doesn't exist, returns nullptr
|
CStackInstance * getStackPtr(const SlotID & slot) const; //if stack doesn't exist, returns nullptr
|
||||||
const CCreature * getCreature(const SlotID & slot) const; //workaround of map issue;
|
const CCreature * getCreature(const SlotID & slot) const; //workaround of map issue;
|
||||||
int getStackCount(const SlotID & slot) const;
|
int getStackCount(const SlotID & slot) const;
|
||||||
TExpType getStackExperience(const SlotID & slot) const;
|
TExpType getStackExperience(const SlotID & slot) const;
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
#include "gameState/TavernHeroesPool.h"
|
#include "gameState/TavernHeroesPool.h"
|
||||||
#include "gameState/QuestInfo.h"
|
#include "gameState/QuestInfo.h"
|
||||||
#include "mapObjects/CGHeroInstance.h"
|
#include "mapObjects/CGHeroInstance.h"
|
||||||
|
#include "networkPacks/ArtifactLocation.h"
|
||||||
#include "CGeneralTextHandler.h"
|
#include "CGeneralTextHandler.h"
|
||||||
#include "StartInfo.h" // for StartInfo
|
#include "StartInfo.h" // for StartInfo
|
||||||
#include "battle/BattleInfo.h" // for BattleInfo
|
#include "battle/BattleInfo.h" // for BattleInfo
|
||||||
@ -966,6 +967,22 @@ const CGObjectInstance * CGameInfoCallback::getObjInstance( ObjectInstanceID oid
|
|||||||
return gs->map->objects[oid.num];
|
return gs->map->objects[oid.num];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CArtifactSet * CGameInfoCallback::getArtSet(const ArtifactLocation & loc) const
|
||||||
|
{
|
||||||
|
auto hero = const_cast<CGHeroInstance*>(getHero(loc.artHolder));
|
||||||
|
if(loc.creature.has_value())
|
||||||
|
{
|
||||||
|
if(loc.creature.value() == SlotID::COMMANDER_SLOT_PLACEHOLDER)
|
||||||
|
return hero->commander;
|
||||||
|
else
|
||||||
|
return hero->getStackPtr(loc.creature.value());
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
return hero;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
std::vector<ObjectInstanceID> CGameInfoCallback::getVisibleTeleportObjects(std::vector<ObjectInstanceID> ids, PlayerColor player) const
|
std::vector<ObjectInstanceID> CGameInfoCallback::getVisibleTeleportObjects(std::vector<ObjectInstanceID> ids, PlayerColor player) const
|
||||||
{
|
{
|
||||||
vstd::erase_if(ids, [&](const ObjectInstanceID & id) -> bool
|
vstd::erase_if(ids, [&](const ObjectInstanceID & id) -> bool
|
||||||
|
@ -40,6 +40,8 @@ class CGameState;
|
|||||||
class PathfinderConfig;
|
class PathfinderConfig;
|
||||||
struct TurnTimerInfo;
|
struct TurnTimerInfo;
|
||||||
|
|
||||||
|
struct ArtifactLocation;
|
||||||
|
class CArtifactSet;
|
||||||
class CArmedInstance;
|
class CArmedInstance;
|
||||||
class CGObjectInstance;
|
class CGObjectInstance;
|
||||||
class CGHeroInstance;
|
class CGHeroInstance;
|
||||||
@ -174,6 +176,7 @@ public:
|
|||||||
virtual int64_t estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
|
virtual int64_t estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
|
||||||
virtual const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const;
|
virtual const CArtifactInstance * getArtInstance(ArtifactInstanceID aid) const;
|
||||||
virtual const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const;
|
virtual const CGObjectInstance * getObjInstance(ObjectInstanceID oid) const;
|
||||||
|
virtual CArtifactSet * getArtSet(const ArtifactLocation & loc) const;
|
||||||
//virtual const CGObjectInstance * getArmyInstance(ObjectInstanceID oid) const;
|
//virtual const CGObjectInstance * getArmyInstance(ObjectInstanceID oid) const;
|
||||||
|
|
||||||
//objects
|
//objects
|
||||||
|
@ -607,20 +607,23 @@ public:
|
|||||||
TRANSITION_POS = -3,
|
TRANSITION_POS = -3,
|
||||||
FIRST_AVAILABLE = -2,
|
FIRST_AVAILABLE = -2,
|
||||||
PRE_FIRST = -1, //sometimes used as error, sometimes as first free in backpack
|
PRE_FIRST = -1, //sometimes used as error, sometimes as first free in backpack
|
||||||
|
|
||||||
|
// Hero
|
||||||
HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, //5
|
HEAD, SHOULDERS, NECK, RIGHT_HAND, LEFT_HAND, TORSO, //5
|
||||||
RIGHT_RING, LEFT_RING, FEET, //8
|
RIGHT_RING, LEFT_RING, FEET, //8
|
||||||
MISC1, MISC2, MISC3, MISC4, //12
|
MISC1, MISC2, MISC3, MISC4, //12
|
||||||
MACH1, MACH2, MACH3, MACH4, //16
|
MACH1, MACH2, MACH3, MACH4, //16
|
||||||
SPELLBOOK, MISC5, //18
|
SPELLBOOK, MISC5, //18
|
||||||
AFTER_LAST,
|
BACKPACK_START = 19,
|
||||||
//cres
|
|
||||||
CREATURE_SLOT = 0,
|
|
||||||
COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6, COMMANDER_AFTER_LAST,
|
|
||||||
|
|
||||||
BACKPACK_START = 19
|
// Creatures
|
||||||
|
CREATURE_SLOT = 0,
|
||||||
|
|
||||||
|
// Commander
|
||||||
|
COMMANDER1 = 0, COMMANDER2, COMMANDER3, COMMANDER4, COMMANDER5, COMMANDER6
|
||||||
};
|
};
|
||||||
|
|
||||||
static_assert (AFTER_LAST == BACKPACK_START, "incorrect number of artifact slots");
|
static_assert(MISC5 < BACKPACK_START, "incorrect number of artifact slots");
|
||||||
|
|
||||||
DLL_LINKAGE static si32 decode(const std::string & identifier);
|
DLL_LINKAGE static si32 decode(const std::string & identifier);
|
||||||
DLL_LINKAGE static std::string encode(const si32 index);
|
DLL_LINKAGE static std::string encode(const si32 index);
|
||||||
|
@ -2105,7 +2105,7 @@ bool CGameState::giveHeroArtifact(CGHeroInstance * h, const ArtifactID & aid)
|
|||||||
auto slot = ArtifactUtils::getArtAnyPosition(h, aid);
|
auto slot = ArtifactUtils::getArtAnyPosition(h, aid);
|
||||||
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
|
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
|
||||||
{
|
{
|
||||||
ai->putAt(ArtifactLocation(h, slot));
|
ai->putAt(*h, slot);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -134,9 +134,9 @@ void CGameStateCampaign::trimCrossoverHeroesParameters(std::vector<CampaignHeroR
|
|||||||
|
|
||||||
bool takeable = travelOptions.artifactsKeptByHero.count(art->artType->getId());
|
bool takeable = travelOptions.artifactsKeptByHero.count(art->artType->getId());
|
||||||
|
|
||||||
ArtifactLocation al(hero, artifactPosition);
|
ArtifactLocation al(hero->id, artifactPosition);
|
||||||
if(!takeable && !al.getSlot()->locked) //don't try removing locked artifacts -> it crashes #1719
|
if(!takeable && !hero->getSlot(al.slot)->locked) //don't try removing locked artifacts -> it crashes #1719
|
||||||
al.removeArtifact();
|
hero->getArt(al.slot)->removeFrom(*hero, al.slot);
|
||||||
};
|
};
|
||||||
|
|
||||||
// process on copy - removal of artifact will invalidate container
|
// 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));
|
CArtifactInstance * scroll = ArtifactUtils::createScroll(SpellID(curBonus->info2));
|
||||||
const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId());
|
const auto slot = ArtifactUtils::getArtAnyPosition(hero, scroll->getTypeId());
|
||||||
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
|
if(ArtifactUtils::isSlotEquipment(slot) || ArtifactUtils::isSlotBackpack(slot))
|
||||||
scroll->putAt(ArtifactLocation(hero, slot));
|
scroll->putAt(*hero, slot);
|
||||||
else
|
else
|
||||||
logGlobal->error("Cannot give starting scroll - no free slots!");
|
logGlobal->error("Cannot give starting scroll - no free slots!");
|
||||||
break;
|
break;
|
||||||
|
@ -1092,7 +1092,7 @@ std::string CGHeroInstance::getBiographyTextID() const
|
|||||||
|
|
||||||
CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
|
CGHeroInstance::ArtPlacementMap CGHeroInstance::putArtifact(ArtifactPosition pos, CArtifactInstance * art)
|
||||||
{
|
{
|
||||||
assert(art->artType->canBePutAt(this, pos));
|
assert(art->canBePutAt(this, pos));
|
||||||
|
|
||||||
if(ArtifactUtils::isSlotEquipment(pos))
|
if(ArtifactUtils::isSlotEquipment(pos))
|
||||||
attachTo(*art);
|
attachTo(*art);
|
||||||
@ -1135,7 +1135,7 @@ void CGHeroInstance::removeSpellbook()
|
|||||||
|
|
||||||
if(hasSpellbook())
|
if(hasSpellbook())
|
||||||
{
|
{
|
||||||
ArtifactLocation(this, ArtifactPosition(ArtifactPosition::SPELLBOOK)).removeArtifact();
|
getArt(ArtifactPosition::SPELLBOOK)->removeFrom(*this, ArtifactPosition::SPELLBOOK);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -144,7 +144,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const
|
|||||||
{
|
{
|
||||||
if(h->hasArt(elem))
|
if(h->hasArt(elem))
|
||||||
{
|
{
|
||||||
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(elem, false)));
|
cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(elem, false)));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@ -153,7 +153,7 @@ void CQuest::completeQuest(IGameCallback * cb, const CGHeroInstance *h) const
|
|||||||
auto parts = assembly->getPartsInfo();
|
auto parts = assembly->getPartsInfo();
|
||||||
|
|
||||||
// Remove the assembly
|
// Remove the assembly
|
||||||
cb->removeArtifact(ArtifactLocation(h, h->getArtPos(assembly)));
|
cb->removeArtifact(ArtifactLocation(h->id, h->getArtPos(assembly)));
|
||||||
|
|
||||||
// Disassemble this backpack artifact
|
// Disassemble this backpack artifact
|
||||||
for(const auto & ci : parts)
|
for(const auto & ci : parts)
|
||||||
|
@ -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
|
// 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 dstLoc = ArtifactLocation(hero, ArtifactPosition(slot));
|
if(artifact->canBePutAt(hero, ArtifactPosition(slot)))
|
||||||
if(artifact->canBePutAt(dstLoc))
|
|
||||||
{
|
{
|
||||||
artifact->putAt(dstLoc);
|
artifact->putAt(*hero, ArtifactPosition(slot));
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
@ -9,67 +9,34 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../ConstTransitivePtr.h"
|
|
||||||
#include "../constants/EntityIdentifiers.h"
|
#include "../constants/EntityIdentifiers.h"
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class CGHeroInstance;
|
|
||||||
class CStackInstance;
|
|
||||||
class CArmedInstance;
|
|
||||||
class CArtifactSet;
|
|
||||||
class CBonusSystemNode;
|
|
||||||
struct ArtSlotInfo;
|
|
||||||
|
|
||||||
using TArtHolder = std::variant<ConstTransitivePtr<CGHeroInstance>, ConstTransitivePtr<CStackInstance>>;
|
|
||||||
|
|
||||||
struct ArtifactLocation
|
struct ArtifactLocation
|
||||||
{
|
{
|
||||||
TArtHolder artHolder;//TODO: identify holder by id
|
ObjectInstanceID artHolder;
|
||||||
ArtifactPosition slot = ArtifactPosition::PRE_FIRST;
|
ArtifactPosition slot;
|
||||||
|
std::optional<SlotID> creature;
|
||||||
|
|
||||||
ArtifactLocation()
|
ArtifactLocation()
|
||||||
: artHolder(ConstTransitivePtr<CGHeroInstance>())
|
: artHolder(ObjectInstanceID::NONE)
|
||||||
|
, slot(ArtifactPosition::PRE_FIRST)
|
||||||
|
, creature(std::nullopt)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
template<typename T>
|
ArtifactLocation(const ObjectInstanceID id, const ArtifactPosition & slot = ArtifactPosition::PRE_FIRST)
|
||||||
ArtifactLocation(const T * ArtHolder, ArtifactPosition Slot)
|
: artHolder(id)
|
||||||
: artHolder(const_cast<T *>(ArtHolder)) //we are allowed here to const cast -> change will go through one of our packages... do not abuse!
|
, slot(slot)
|
||||||
, slot(Slot)
|
, creature(std::nullopt)
|
||||||
{
|
|
||||||
}
|
|
||||||
ArtifactLocation(TArtHolder ArtHolder, const ArtifactPosition & Slot)
|
|
||||||
: artHolder(std::move(std::move(ArtHolder)))
|
|
||||||
, slot(Slot)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
|
||||||
bool isHolder(const T *t) const
|
|
||||||
{
|
|
||||||
if(auto ptrToT = std::get<ConstTransitivePtr<T>>(artHolder))
|
|
||||||
{
|
|
||||||
return ptrToT == t;
|
|
||||||
}
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
DLL_LINKAGE void removeArtifact(); // BE CAREFUL, this operation modifies holder (gs)
|
|
||||||
|
|
||||||
DLL_LINKAGE const CArmedInstance *relatedObj() const; //hero or the stack owner
|
|
||||||
DLL_LINKAGE PlayerColor owningPlayer() const;
|
|
||||||
DLL_LINKAGE CArtifactSet *getHolderArtSet();
|
|
||||||
DLL_LINKAGE CBonusSystemNode *getHolderNode();
|
|
||||||
DLL_LINKAGE CArtifactSet *getHolderArtSet() const;
|
|
||||||
DLL_LINKAGE const CBonusSystemNode *getHolderNode() const;
|
|
||||||
|
|
||||||
DLL_LINKAGE const CArtifactInstance *getArt() const;
|
|
||||||
DLL_LINKAGE CArtifactInstance *getArt();
|
|
||||||
DLL_LINKAGE const ArtSlotInfo *getSlot() const;
|
|
||||||
template <typename Handler> void serialize(Handler & h, const int version)
|
template <typename Handler> void serialize(Handler & h, const int version)
|
||||||
{
|
{
|
||||||
h & artHolder;
|
h & artHolder;
|
||||||
h & slot;
|
h & slot;
|
||||||
|
h & creature;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -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)
|
void ChangeStackCount::applyGs(CGameState * gs)
|
||||||
{
|
{
|
||||||
auto * srcObj = gs->getArmyInstance(army);
|
auto * srcObj = gs->getArmyInstance(army);
|
||||||
@ -1709,39 +1648,40 @@ void RebalanceStacks::applyGs(CGameState * gs)
|
|||||||
|
|
||||||
if(srcCount == count) //moving whole stack
|
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
|
if(c) //stack at dest -> merge
|
||||||
{
|
{
|
||||||
assert(c == srcType);
|
assert(c == srcType);
|
||||||
auto alHere = ArtifactLocation (src.getStack(), ArtifactPosition::CREATURE_SLOT);
|
|
||||||
auto alDest = ArtifactLocation (dst.getStack(), ArtifactPosition::CREATURE_SLOT);
|
const auto srcHero = dynamic_cast<CGHeroInstance*>(src.army.get());
|
||||||
auto * artHere = alHere.getArt();
|
const auto dstHero = dynamic_cast<CGHeroInstance*>(dst.army.get());
|
||||||
auto * artDest = alDest.getArt();
|
auto srcStack = const_cast<CStackInstance*>(src.getStack());
|
||||||
if (artHere)
|
auto dstStack = const_cast<CStackInstance*>(dst.getStack());
|
||||||
|
if(auto srcArt = srcStack->getArt(ArtifactPosition::CREATURE_SLOT))
|
||||||
{
|
{
|
||||||
if (alDest.getArt())
|
if(auto dstArt = dstStack->getArt(ArtifactPosition::CREATURE_SLOT))
|
||||||
{
|
{
|
||||||
auto * hero = dynamic_cast<CGHeroInstance *>(src.army.get());
|
auto dstSlot = ArtifactUtils::getArtBackpackPosition(srcHero, dstArt->getTypeId());
|
||||||
auto dstSlot = ArtifactUtils::getArtBackpackPosition(hero, alDest.getArt()->getTypeId());
|
if(srcHero && dstSlot != ArtifactPosition::PRE_FIRST)
|
||||||
if(hero && dstSlot != ArtifactPosition::PRE_FIRST)
|
|
||||||
{
|
{
|
||||||
artDest->move (alDest, ArtifactLocation (hero, dstSlot));
|
dstArt->move(*dstStack, ArtifactPosition::CREATURE_SLOT, *srcHero, dstSlot);
|
||||||
}
|
}
|
||||||
//else - artifact cna be lost :/
|
//else - artifact cna be lost :/
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
EraseArtifact ea;
|
EraseArtifact ea;
|
||||||
ea.al = alDest;
|
ea.al = ArtifactLocation(dstHero->id, ArtifactPosition::CREATURE_SLOT);
|
||||||
|
ea.al.creature = dst.slot;
|
||||||
ea.applyGs(gs);
|
ea.applyGs(gs);
|
||||||
logNetwork->warn("Cannot move artifact! No free slots");
|
logNetwork->warn("Cannot move artifact! No free slots");
|
||||||
}
|
}
|
||||||
artHere->move (alHere, alDest);
|
srcArt->move(*srcStack, ArtifactPosition::CREATURE_SLOT, *dstStack, ArtifactPosition::CREATURE_SLOT);
|
||||||
//TODO: choose from dialog
|
//TODO: choose from dialog
|
||||||
}
|
}
|
||||||
else //just move to the other slot before stack gets erased
|
else //just move to the other slot before stack gets erased
|
||||||
{
|
{
|
||||||
artHere->move (alHere, alDest);
|
srcArt->move(*srcStack, ArtifactPosition::CREATURE_SLOT, *dstStack, ArtifactPosition::CREATURE_SLOT);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (stackExp)
|
if (stackExp)
|
||||||
@ -1811,53 +1751,57 @@ void BulkSmartRebalanceStacks::applyGs(CGameState * gs)
|
|||||||
|
|
||||||
void PutArtifact::applyGs(CGameState *gs)
|
void PutArtifact::applyGs(CGameState *gs)
|
||||||
{
|
{
|
||||||
assert(art->canBePutAt(al));
|
|
||||||
// Ensure that artifact has been correctly added via NewArtifact pack
|
// Ensure that artifact has been correctly added via NewArtifact pack
|
||||||
assert(vstd::contains(gs->map->artInstances, art));
|
assert(vstd::contains(gs->map->artInstances, art));
|
||||||
assert(!art->getParentNodes().empty());
|
assert(!art->getParentNodes().empty());
|
||||||
art->putAt(al);
|
auto hero = gs->getHero(al.artHolder);
|
||||||
|
assert(hero);
|
||||||
|
assert(art && art->canBePutAt(hero, al.slot));
|
||||||
|
art->putAt(*hero, al.slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void EraseArtifact::applyGs(CGameState *gs)
|
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)
|
if(slot->locked)
|
||||||
{
|
{
|
||||||
logGlobal->debug("Erasing locked artifact: %s", slot->artifact->artType->getNameTranslated());
|
logGlobal->debug("Erasing locked artifact: %s", slot->artifact->artType->getNameTranslated());
|
||||||
DisassembledArtifact dis;
|
DisassembledArtifact dis;
|
||||||
dis.al.artHolder = al.artHolder;
|
dis.al.artHolder = al.artHolder;
|
||||||
auto * aset = al.getHolderArtSet();
|
|
||||||
#ifndef NDEBUG
|
for(auto & slotInfo : hero->artifactsWorn)
|
||||||
bool found = false;
|
|
||||||
#endif
|
|
||||||
for(auto& p : aset->artifactsWorn)
|
|
||||||
{
|
{
|
||||||
auto art = p.second.artifact;
|
auto art = slotInfo.second.artifact;
|
||||||
if(art->isCombined() && art->isPart(slot->artifact))
|
if(art->isCombined() && art->isPart(slot->artifact))
|
||||||
{
|
{
|
||||||
dis.al.slot = aset->getArtPos(art);
|
dis.al.slot = hero->getArtPos(art);
|
||||||
#ifndef NDEBUG
|
|
||||||
found = true;
|
|
||||||
#endif
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
assert(found && "Failed to determine the assembly this locked artifact belongs to");
|
assert((dis.al.slot != ArtifactPosition::PRE_FIRST) && "Failed to determine the assembly this locked artifact belongs to");
|
||||||
logGlobal->debug("Found the corresponding assembly: %s", dis.al.getSlot()->artifact->artType->getNameTranslated());
|
logGlobal->debug("Found the corresponding assembly: %s", hero->getArt(dis.al.slot)->artType->getNameTranslated());
|
||||||
dis.applyGs(gs);
|
dis.applyGs(gs);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
logGlobal->debug("Erasing artifact %s", slot->artifact->artType->getNameTranslated());
|
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)
|
void MoveArtifact::applyGs(CGameState * gs)
|
||||||
{
|
{
|
||||||
CArtifactInstance * art = src.getArt();
|
auto srcHero = gs->getArtSet(src);
|
||||||
assert(!ArtifactUtils::isSlotEquipment(dst.slot) || !dst.getArt());
|
auto dstHero = gs->getArtSet(dst);
|
||||||
art->move(src, dst);
|
assert(srcHero);
|
||||||
|
assert(dstHero);
|
||||||
|
auto art = srcHero->getArt(src.slot);
|
||||||
|
assert(art && art->canBePutAt(dstHero, dst.slot));
|
||||||
|
art->move(*srcHero, src.slot, *dstHero, dst.slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BulkMoveArtifacts::applyGs(CGameState * gs)
|
void BulkMoveArtifacts::applyGs(CGameState * gs)
|
||||||
@ -1869,8 +1813,8 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
|
|||||||
BULK_PUT
|
BULK_PUT
|
||||||
};
|
};
|
||||||
|
|
||||||
auto bulkArtsOperation = [this](std::vector<LinkedSlots> & artsPack,
|
auto bulkArtsOperation = [this, gs](std::vector<LinkedSlots> & artsPack,
|
||||||
CArtifactSet * artSet, EBulkArtsOp operation) -> void
|
CArtifactSet & artSet, EBulkArtsOp operation) -> void
|
||||||
{
|
{
|
||||||
int numBackpackArtifactsMoved = 0;
|
int numBackpackArtifactsMoved = 0;
|
||||||
for(auto & slot : artsPack)
|
for(auto & slot : artsPack)
|
||||||
@ -1883,21 +1827,18 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
|
|||||||
{
|
{
|
||||||
srcPos = ArtifactPosition(srcPos.num - numBackpackArtifactsMoved);
|
srcPos = ArtifactPosition(srcPos.num - numBackpackArtifactsMoved);
|
||||||
}
|
}
|
||||||
const auto * slotInfo = artSet->getSlot(srcPos);
|
auto * art = artSet.getArt(srcPos);
|
||||||
assert(slotInfo);
|
|
||||||
auto * art = const_cast<CArtifactInstance *>(slotInfo->getArt());
|
|
||||||
assert(art);
|
assert(art);
|
||||||
switch(operation)
|
switch(operation)
|
||||||
{
|
{
|
||||||
case EBulkArtsOp::BULK_MOVE:
|
case EBulkArtsOp::BULK_MOVE:
|
||||||
const_cast<CArtifactInstance*>(art)->move(
|
art->move(artSet, srcPos, *gs->getHero(dstArtHolder), slot.dstPos);
|
||||||
ArtifactLocation(srcArtHolder, srcPos), ArtifactLocation(dstArtHolder, slot.dstPos));
|
|
||||||
break;
|
break;
|
||||||
case EBulkArtsOp::BULK_REMOVE:
|
case EBulkArtsOp::BULK_REMOVE:
|
||||||
art->removeFrom(ArtifactLocation(dstArtHolder, srcPos));
|
art->removeFrom(artSet, srcPos);
|
||||||
break;
|
break;
|
||||||
case EBulkArtsOp::BULK_PUT:
|
case EBulkArtsOp::BULK_PUT:
|
||||||
art->putAt(ArtifactLocation(srcArtHolder, slot.dstPos));
|
art->putAt(*gs->getHero(srcArtHolder), slot.dstPos);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
@ -1910,37 +1851,38 @@ void BulkMoveArtifacts::applyGs(CGameState * gs)
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
auto * leftSet = gs->getArtSet(ArtifactLocation(srcArtHolder));
|
||||||
if(swap)
|
if(swap)
|
||||||
{
|
{
|
||||||
// Swap
|
// Swap
|
||||||
auto * leftSet = getSrcHolderArtSet();
|
auto * rightSet = gs->getArtSet(ArtifactLocation(dstArtHolder));
|
||||||
auto * rightSet = getDstHolderArtSet();
|
|
||||||
CArtifactFittingSet artFittingSet(leftSet->bearerType());
|
CArtifactFittingSet artFittingSet(leftSet->bearerType());
|
||||||
|
|
||||||
artFittingSet.artifactsWorn = rightSet->artifactsWorn;
|
artFittingSet.artifactsWorn = rightSet->artifactsWorn;
|
||||||
artFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack;
|
artFittingSet.artifactsInBackpack = rightSet->artifactsInBackpack;
|
||||||
|
|
||||||
bulkArtsOperation(artsPack1, rightSet, EBulkArtsOp::BULK_REMOVE);
|
bulkArtsOperation(artsPack1, *rightSet, EBulkArtsOp::BULK_REMOVE);
|
||||||
bulkArtsOperation(artsPack0, leftSet, EBulkArtsOp::BULK_MOVE);
|
bulkArtsOperation(artsPack0, *leftSet, EBulkArtsOp::BULK_MOVE);
|
||||||
bulkArtsOperation(artsPack1, &artFittingSet, EBulkArtsOp::BULK_PUT);
|
bulkArtsOperation(artsPack1, artFittingSet, EBulkArtsOp::BULK_PUT);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
bulkArtsOperation(artsPack0, getSrcHolderArtSet(), EBulkArtsOp::BULK_MOVE);
|
bulkArtsOperation(artsPack0, *leftSet, EBulkArtsOp::BULK_MOVE);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void AssembledArtifact::applyGs(CGameState *gs)
|
void AssembledArtifact::applyGs(CGameState *gs)
|
||||||
{
|
{
|
||||||
CArtifactSet * artSet = al.getHolderArtSet();
|
auto hero = gs->getHero(al.artHolder);
|
||||||
const CArtifactInstance * transformedArt = al.getArt();
|
assert(hero);
|
||||||
|
const auto transformedArt = hero->getArt(al.slot);
|
||||||
assert(transformedArt);
|
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();
|
return art->getId() == builtArt->getId();
|
||||||
}));
|
}));
|
||||||
|
|
||||||
const auto transformedArtSlot = artSet->getSlotByInstance(transformedArt);
|
const auto transformedArtSlot = hero->getSlotByInstance(transformedArt);
|
||||||
auto * combinedArt = new CArtifactInstance(builtArt);
|
auto * combinedArt = new CArtifactInstance(builtArt);
|
||||||
gs->map->addNewArtifactInstance(combinedArt);
|
gs->map->addNewArtifactInstance(combinedArt);
|
||||||
|
|
||||||
@ -1952,7 +1894,7 @@ void AssembledArtifact::applyGs(CGameState *gs)
|
|||||||
if(transformedArt->getTypeId() == constituent->getId())
|
if(transformedArt->getTypeId() == constituent->getId())
|
||||||
slot = transformedArtSlot;
|
slot = transformedArtSlot;
|
||||||
else
|
else
|
||||||
slot = artSet->getArtPos(constituent->getId(), false, false);
|
slot = hero->getArtPos(constituent->getId(), false, false);
|
||||||
|
|
||||||
assert(slot != ArtifactPosition::PRE_FIRST);
|
assert(slot != ArtifactPosition::PRE_FIRST);
|
||||||
slotsInvolved.emplace_back(slot);
|
slotsInvolved.emplace_back(slot);
|
||||||
@ -1972,8 +1914,8 @@ void AssembledArtifact::applyGs(CGameState *gs)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(!vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), al.slot)
|
if(!vstd::contains(combinedArt->artType->getPossibleSlots().at(hero->bearerType()), al.slot)
|
||||||
&& vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), slot))
|
&& vstd::contains(combinedArt->artType->getPossibleSlots().at(hero->bearerType()), slot))
|
||||||
al.slot = slot;
|
al.slot = slot;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@ -1986,8 +1928,8 @@ void AssembledArtifact::applyGs(CGameState *gs)
|
|||||||
// Delete parts from hero
|
// Delete parts from hero
|
||||||
for(const auto slot : slotsInvolved)
|
for(const auto slot : slotsInvolved)
|
||||||
{
|
{
|
||||||
const auto constituentInstance = artSet->getArt(slot);
|
const auto constituentInstance = hero->getArt(slot);
|
||||||
constituentInstance->removeFrom(ArtifactLocation(al.artHolder, slot));
|
constituentInstance->removeFrom(*hero, slot);
|
||||||
|
|
||||||
if(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot)
|
if(ArtifactUtils::isSlotEquipment(al.slot) && slot != al.slot)
|
||||||
combinedArt->addPart(constituentInstance, slot);
|
combinedArt->addPart(constituentInstance, slot);
|
||||||
@ -1996,25 +1938,26 @@ void AssembledArtifact::applyGs(CGameState *gs)
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Put new combined artifacts
|
// Put new combined artifacts
|
||||||
combinedArt->putAt(al);
|
combinedArt->putAt(*hero, al.slot);
|
||||||
}
|
}
|
||||||
|
|
||||||
void DisassembledArtifact::applyGs(CGameState *gs)
|
void DisassembledArtifact::applyGs(CGameState *gs)
|
||||||
{
|
{
|
||||||
auto * disassembled = al.getArt();
|
auto hero = gs->getHero(al.artHolder);
|
||||||
assert(disassembled);
|
assert(hero);
|
||||||
|
auto disassembledArt = hero->getArt(al.slot);
|
||||||
|
assert(disassembledArt);
|
||||||
|
|
||||||
auto parts = disassembled->getPartsInfo();
|
auto parts = disassembledArt->getPartsInfo();
|
||||||
disassembled->removeFrom(al);
|
disassembledArt->removeFrom(*hero, al.slot);
|
||||||
for(auto & part : parts)
|
for(auto & part : parts)
|
||||||
{
|
{
|
||||||
ArtifactLocation partLoc = al;
|
|
||||||
// ArtifactPosition::PRE_FIRST is value of main part slot -> it'll replace combined artifact in its pos
|
// 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);
|
auto slot = (ArtifactUtils::isSlotEquipment(part.slot) ? part.slot : al.slot);
|
||||||
disassembled->detachFrom(*part.art);
|
disassembledArt->detachFrom(*part.art);
|
||||||
part.art->putAt(partLoc);
|
part.art->putAt(*hero, slot);
|
||||||
}
|
}
|
||||||
gs->map->eraseArtifactInstance(disassembled);
|
gs->map->eraseArtifactInstance(disassembledArt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeroVisit::applyGs(CGameState *gs)
|
void HeroVisit::applyGs(CGameState *gs)
|
||||||
@ -2603,14 +2546,4 @@ const CArtifactInstance * ArtSlotInfo::getArt() const
|
|||||||
return artifact;
|
return artifact;
|
||||||
}
|
}
|
||||||
|
|
||||||
CArtifactSet * BulkMoveArtifacts::getSrcHolderArtSet()
|
|
||||||
{
|
|
||||||
return std::visit(GetBase<CArtifactSet>(), srcArtHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
CArtifactSet * BulkMoveArtifacts::getDstHolderArtSet()
|
|
||||||
{
|
|
||||||
return std::visit(GetBase<CArtifactSet>(), dstArtHolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
@ -1060,14 +1060,16 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
TArtHolder srcArtHolder;
|
ObjectInstanceID srcArtHolder;
|
||||||
TArtHolder dstArtHolder;
|
ObjectInstanceID dstArtHolder;
|
||||||
|
|
||||||
BulkMoveArtifacts()
|
BulkMoveArtifacts()
|
||||||
: swap(false)
|
: srcArtHolder(ObjectInstanceID::NONE)
|
||||||
|
, dstArtHolder(ObjectInstanceID::NONE)
|
||||||
|
, swap(false)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
BulkMoveArtifacts(TArtHolder srcArtHolder, TArtHolder dstArtHolder, bool swap)
|
BulkMoveArtifacts(const ObjectInstanceID srcArtHolder, const ObjectInstanceID dstArtHolder, bool swap)
|
||||||
: srcArtHolder(std::move(srcArtHolder))
|
: srcArtHolder(std::move(srcArtHolder))
|
||||||
, dstArtHolder(std::move(dstArtHolder))
|
, dstArtHolder(std::move(dstArtHolder))
|
||||||
, swap(swap)
|
, swap(swap)
|
||||||
@ -1079,8 +1081,6 @@ struct DLL_LINKAGE BulkMoveArtifacts : CArtifactOperationPack
|
|||||||
std::vector<LinkedSlots> artsPack0;
|
std::vector<LinkedSlots> artsPack0;
|
||||||
std::vector<LinkedSlots> artsPack1;
|
std::vector<LinkedSlots> artsPack1;
|
||||||
bool swap;
|
bool swap;
|
||||||
CArtifactSet * getSrcHolderArtSet();
|
|
||||||
CArtifactSet * getDstHolderArtSet();
|
|
||||||
|
|
||||||
void visitTyped(ICPackVisitor & visitor) override;
|
void visitTyped(ICPackVisitor & visitor) override;
|
||||||
|
|
||||||
|
@ -2270,7 +2270,7 @@ bool CGameHandler::buildStructure(ObjectInstanceID tid, BuildingID requestedID,
|
|||||||
if(!t->visitingHero || !t->visitingHero->hasArt(ArtifactID::GRAIL))
|
if(!t->visitingHero || !t->visitingHero->hasArt(ArtifactID::GRAIL))
|
||||||
COMPLAIN_RET("Cannot build this without grail!")
|
COMPLAIN_RET("Cannot build this without grail!")
|
||||||
else
|
else
|
||||||
removeArtifact(ArtifactLocation(t->visitingHero, t->visitingHero->getArtPos(ArtifactID::GRAIL, false)));
|
removeArtifact(ArtifactLocation(t->visitingHero->id, t->visitingHero->getArtPos(ArtifactID::GRAIL, false)));
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -2664,65 +2664,66 @@ bool CGameHandler::garrisonSwap(ObjectInstanceID tid)
|
|||||||
|
|
||||||
// With the amount of changes done to the function, it's more like transferArtifacts.
|
// 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.
|
// 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;
|
ArtifactLocation srcLoc = src, dstLoc = dst;
|
||||||
const PlayerColor srcPlayer = src.owningPlayer(), dstPlayer = dst.owningPlayer();
|
const auto srcArtSet = getArtSet(srcLoc);
|
||||||
const CArmedInstance *srcObj = src.relatedObj(), *dstObj = dst.relatedObj();
|
const auto dstArtSet = getArtSet(dstLoc);
|
||||||
|
assert(srcArtSet);
|
||||||
|
assert(dstArtSet);
|
||||||
|
|
||||||
// Make sure exchange is even possible between the two heroes.
|
// 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!");
|
COMPLAIN_RET("That heroes cannot make any exchange!");
|
||||||
|
|
||||||
const CArtifactInstance *srcArtifact = src.getArt();
|
const auto srcArtifact = srcArtSet->getArt(srcLoc.slot);
|
||||||
const CArtifactInstance *destArtifact = dst.getArt();
|
const auto dstArtifact = dstArtSet->getArt(dstLoc.slot);
|
||||||
const bool isDstSlotBackpack = ArtifactUtils::isSlotBackpack(dst.slot);
|
const bool isDstSlotBackpack = dstArtSet->bearerType() == ArtBearer::HERO ? ArtifactUtils::isSlotBackpack(dstLoc.slot) : false;
|
||||||
|
|
||||||
if(srcArtifact == nullptr)
|
if(srcArtifact == nullptr)
|
||||||
COMPLAIN_RET("No artifact to move!");
|
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!");
|
COMPLAIN_RET("Can't touch artifact on hero of another player!");
|
||||||
|
|
||||||
// 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)
|
if((!srcArtifact || !isDstSlotBackpack) && srcArtifact && !srcArtifact->canBePutAt(dstArtSet, dstLoc.slot, true))
|
||||||
&& srcArtifact && !srcArtifact->canBePutAt(dst, true))
|
|
||||||
COMPLAIN_RET("Cannot move artifact!");
|
COMPLAIN_RET("Cannot move artifact!");
|
||||||
|
|
||||||
auto srcSlot = src.getSlot();
|
auto srcSlotInfo = srcArtSet->getSlot(srcLoc.slot);
|
||||||
auto dstSlot = dst.getSlot();
|
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.");
|
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(srcLoc.slot == ArtifactPosition::MACH4 || dstLoc.slot == ArtifactPosition::MACH4)
|
||||||
COMPLAIN_RET("Cannot move catapult!");
|
COMPLAIN_RET("Cannot move catapult!");
|
||||||
|
|
||||||
if(isDstSlotBackpack)
|
if(isDstSlotBackpack)
|
||||||
{
|
{
|
||||||
if(!ArtifactUtils::isBackpackFreeSlots(dst.getHolderArtSet()))
|
if(!ArtifactUtils::isBackpackFreeSlots(dstArtSet))
|
||||||
COMPLAIN_RET("Backpack is full!");
|
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!");
|
COMPLAIN_RET("Won't move artifact: Dest same as source!");
|
||||||
|
|
||||||
// Check if dst slot is occupied
|
// Check if dst slot is occupied
|
||||||
if(!isDstSlotBackpack && destArtifact)
|
if(!isDstSlotBackpack && dstArtifact)
|
||||||
{
|
{
|
||||||
// Previous artifact must be removed first
|
// Previous artifact must be removed first
|
||||||
moveArtifact(dst, ArtifactLocation(dst.artHolder, ArtifactPosition::TRANSITION_POS));
|
moveArtifact(dstLoc, ArtifactLocation(dstLoc.artHolder, ArtifactPosition::TRANSITION_POS));
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
auto hero = std::get<ConstTransitivePtr<CGHeroInstance>>(dst.artHolder);
|
auto hero = getHero(dst.artHolder);
|
||||||
if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dst.slot))
|
if(ArtifactUtils::checkSpellbookIsNeeded(hero, srcArtifact->artType->getId(), dstLoc.slot))
|
||||||
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
giveHeroNewArtifact(hero, VLC->arth->objects[ArtifactID::SPELLBOOK], ArtifactPosition::SPELLBOOK);
|
||||||
}
|
}
|
||||||
catch(const std::bad_variant_access &)
|
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
|
// object other than hero received an art - ignore
|
||||||
}
|
}
|
||||||
|
|
||||||
MoveArtifact ma(&src, &dst);
|
MoveArtifact ma(&srcLoc, &dstLoc);
|
||||||
if(src.artHolder == dst.artHolder)
|
if(srcLoc.artHolder == dstLoc.artHolder)
|
||||||
ma.askAssemble = false;
|
ma.askAssemble = false;
|
||||||
sendAndApply(&ma);
|
sendAndApply(&ma);
|
||||||
}
|
}
|
||||||
@ -2749,8 +2750,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
|
|||||||
if((!psrcHero) || (!pdstHero))
|
if((!psrcHero) || (!pdstHero))
|
||||||
COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID");
|
COMPLAIN_RET("bulkMoveArtifacts: wrong hero's ID");
|
||||||
|
|
||||||
BulkMoveArtifacts ma(static_cast<ConstTransitivePtr<CGHeroInstance>>(psrcHero),
|
BulkMoveArtifacts ma(srcHero, dstHero, swap);
|
||||||
static_cast<ConstTransitivePtr<CGHeroInstance>>(pdstHero), swap);
|
|
||||||
auto & slotsSrcDst = ma.artsPack0;
|
auto & slotsSrcDst = ma.artsPack0;
|
||||||
auto & slotsDstSrc = ma.artsPack1;
|
auto & slotsDstSrc = ma.artsPack1;
|
||||||
|
|
||||||
@ -2854,7 +2854,7 @@ bool CGameHandler::assembleArtifacts(ObjectInstanceID heroID, ArtifactPosition a
|
|||||||
if(!destArtifact)
|
if(!destArtifact)
|
||||||
COMPLAIN_RET("assembleArtifacts: there is no such artifact instance!");
|
COMPLAIN_RET("assembleArtifacts: there is no such artifact instance!");
|
||||||
|
|
||||||
const auto dstLoc = ArtifactLocation(hero, artifactSlot);
|
const auto dstLoc = ArtifactLocation(hero->id, artifactSlot);
|
||||||
if(assemble)
|
if(assemble)
|
||||||
{
|
{
|
||||||
CArtifact * combinedArt = VLC->arth->objects[assembleTo];
|
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!");
|
COMPLAIN_RET("assembleArtifacts: It's impossible to assemble requested artifact!");
|
||||||
}
|
}
|
||||||
if(!destArtifact->canBePutAt(dstLoc)
|
if(!destArtifact->canBePutAt(hero, artifactSlot)
|
||||||
&& !destArtifact->canBePutAt(ArtifactLocation(hero, ArtifactPosition::BACKPACK_START)))
|
&& !destArtifact->canBePutAt(hero, ArtifactPosition::BACKPACK_START))
|
||||||
{
|
{
|
||||||
COMPLAIN_RET("assembleArtifacts: It's impossible to give the artholder requested artifact!");
|
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)
|
bool CGameHandler::eraseArtifactByClient(const ArtifactLocation & al)
|
||||||
{
|
{
|
||||||
const auto * hero = getHero(al.relatedObj()->id);
|
const auto * hero = getHero(al.artHolder);
|
||||||
if(hero == nullptr)
|
if(hero == nullptr)
|
||||||
COMPLAIN_RET("eraseArtifactByClient: wrong hero's ID");
|
COMPLAIN_RET("eraseArtifactByClient: wrong hero's ID");
|
||||||
|
|
||||||
const auto * art = al.getArt();
|
const auto * art = hero->getArt(al.slot);
|
||||||
if(art == nullptr)
|
if(art == nullptr)
|
||||||
COMPLAIN_RET("Cannot remove artifact!");
|
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");
|
COMPLAIN_RET("Illegal artifact removal request");
|
||||||
|
|
||||||
removeArtifact(al);
|
removeArtifact(al);
|
||||||
@ -3012,7 +3012,7 @@ bool CGameHandler::sellArtifact(const IMarket *m, const CGHeroInstance *h, Artif
|
|||||||
int resVal = 0, dump = 1;
|
int resVal = 0, dump = 1;
|
||||||
m->getOffer(art->artType->getId(), rid, dump, resVal, EMarketMode::ARTIFACT_RESOURCE);
|
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);
|
giveResource(h->tempOwner, rid, resVal);
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -3750,8 +3750,8 @@ bool CGameHandler::sacrificeArtifact(const IMarket * m, const CGHeroInstance * h
|
|||||||
|
|
||||||
for(int i = 0; i < slot.size(); ++i)
|
for(int i = 0; i < slot.size(); ++i)
|
||||||
{
|
{
|
||||||
ArtifactLocation al(hero, slot[i]);
|
ArtifactLocation al(hero->id, slot[i]);
|
||||||
const CArtifactInstance * a = al.getArt();
|
const CArtifactInstance * a = hero->getArt(al.slot);
|
||||||
|
|
||||||
if(!a)
|
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)
|
bool CGameHandler::giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos)
|
||||||
{
|
{
|
||||||
assert(a->artType);
|
assert(a->artType);
|
||||||
ArtifactLocation al(h, ArtifactPosition::PRE_FIRST);
|
ArtifactLocation al(h->id, ArtifactPosition::PRE_FIRST);
|
||||||
|
|
||||||
if(pos == ArtifactPosition::FIRST_AVAILABLE)
|
if(pos == ArtifactPosition::FIRST_AVAILABLE)
|
||||||
{
|
{
|
||||||
@ -3978,7 +3978,7 @@ bool CGameHandler::giveHeroArtifact(const CGHeroInstance * h, const CArtifactIns
|
|||||||
al.slot = pos;
|
al.slot = pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
if(a->canBePutAt(al))
|
if(a->canBePutAt(h, al.slot))
|
||||||
putArtifact(al, a);
|
putArtifact(al, a);
|
||||||
else
|
else
|
||||||
return false;
|
return false;
|
||||||
|
@ -130,7 +130,7 @@ public:
|
|||||||
bool giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos) override;
|
bool giveHeroArtifact(const CGHeroInstance * h, const CArtifactInstance * a, ArtifactPosition pos) override;
|
||||||
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 & src, const ArtifactLocation & dst) override;
|
||||||
bool bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID dstHero, bool swap, bool equipped, bool backpack);
|
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();
|
||||||
|
@ -134,7 +134,7 @@ void ApplyGhNetPackVisitor::visitGarrisonHeroSwap(GarrisonHeroSwap & pack)
|
|||||||
|
|
||||||
void ApplyGhNetPackVisitor::visitExchangeArtifacts(ExchangeArtifacts & 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);
|
result = gh.moveArtifact(pack.src, pack.dst);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -154,7 +154,7 @@ void ApplyGhNetPackVisitor::visitAssembleArtifacts(AssembleArtifacts & pack)
|
|||||||
|
|
||||||
void ApplyGhNetPackVisitor::visitEraseArtifactByClient(EraseArtifactByClient & 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);
|
result = gh.eraseArtifactByClient(pack.al);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -79,7 +79,7 @@ CasualtiesAfterBattle::CasualtiesAfterBattle(const CBattleInfoCallback & battle,
|
|||||||
logGlobal->debug("War machine has been destroyed");
|
logGlobal->debug("War machine has been destroyed");
|
||||||
auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
|
auto hero = dynamic_ptr_cast<CGHeroInstance> (army);
|
||||||
if (hero)
|
if (hero)
|
||||||
removedWarMachines.push_back (ArtifactLocation(hero, hero->getArtPos(warMachine, true)));
|
removedWarMachines.push_back (ArtifactLocation(hero->id, hero->getArtPos(warMachine, true)));
|
||||||
else
|
else
|
||||||
logGlobal->error("War machine in army without hero");
|
logGlobal->error("War machine in army without hero");
|
||||||
}
|
}
|
||||||
@ -339,7 +339,7 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
|||||||
if(slot != ArtifactPosition::PRE_FIRST)
|
if(slot != ArtifactPosition::PRE_FIRST)
|
||||||
{
|
{
|
||||||
arts.push_back(art);
|
arts.push_back(art);
|
||||||
ma->dst = ArtifactLocation(finishingBattle->winnerHero, slot);
|
ma->dst = ArtifactLocation(finishingBattle->winnerHero->id, slot);
|
||||||
if(ArtifactUtils::isSlotBackpack(slot))
|
if(ArtifactUtils::isSlotBackpack(slot))
|
||||||
ma->askAssemble = false;
|
ma->askAssemble = false;
|
||||||
gameHandler->sendAndApply(ma);
|
gameHandler->sendAndApply(ma);
|
||||||
@ -353,8 +353,8 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
|||||||
for (auto artSlot : artifactsWorn)
|
for (auto artSlot : artifactsWorn)
|
||||||
{
|
{
|
||||||
MoveArtifact ma;
|
MoveArtifact ma;
|
||||||
ma.src = ArtifactLocation(finishingBattle->loserHero, artSlot.first);
|
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
|
||||||
const CArtifactInstance * art = ma.src.getArt();
|
const CArtifactInstance * art = finishingBattle->loserHero->getArt(artSlot.first);
|
||||||
if (art && !art->artType->isBig() &&
|
if (art && !art->artType->isBig() &&
|
||||||
art->artType->getId() != ArtifactID::SPELLBOOK)
|
art->artType->getId() != ArtifactID::SPELLBOOK)
|
||||||
// don't move war machines or locked arts (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
|
//we assume that no big artifacts can be found
|
||||||
MoveArtifact ma;
|
MoveArtifact ma;
|
||||||
ma.src = ArtifactLocation(finishingBattle->loserHero,
|
ma.src = ArtifactLocation(finishingBattle->loserHero->id,
|
||||||
ArtifactPosition(ArtifactPosition::BACKPACK_START + slotNumber)); //backpack automatically shifts arts to beginning
|
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
|
if (art->artType->getId() != ArtifactID::GRAIL) //grail may not be won
|
||||||
{
|
{
|
||||||
sendMoveArtifact(art, &ma);
|
sendMoveArtifact(art, &ma);
|
||||||
@ -380,8 +380,9 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
|||||||
for (auto artSlot : artifactsWorn)
|
for (auto artSlot : artifactsWorn)
|
||||||
{
|
{
|
||||||
MoveArtifact ma;
|
MoveArtifact ma;
|
||||||
ma.src = ArtifactLocation(finishingBattle->loserHero->commander.get(), artSlot.first);
|
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
|
||||||
const CArtifactInstance * art = ma.src.getArt();
|
ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
|
||||||
|
const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
|
||||||
if (art && !art->artType->isBig())
|
if (art && !art->artType->isBig())
|
||||||
{
|
{
|
||||||
sendMoveArtifact(art, &ma);
|
sendMoveArtifact(art, &ma);
|
||||||
@ -395,11 +396,12 @@ void BattleResultProcessor::endBattleConfirm(const CBattleInfoCallback & battle)
|
|||||||
for (auto armySlot : battle.battleGetArmyObject(loser)->stacks)
|
for (auto armySlot : battle.battleGetArmyObject(loser)->stacks)
|
||||||
{
|
{
|
||||||
auto artifactsWorn = armySlot.second->artifactsWorn;
|
auto artifactsWorn = armySlot.second->artifactsWorn;
|
||||||
for (auto artSlot : artifactsWorn)
|
for(const auto & artSlot : artifactsWorn)
|
||||||
{
|
{
|
||||||
MoveArtifact ma;
|
MoveArtifact ma;
|
||||||
ma.src = ArtifactLocation(armySlot.second, artSlot.first);
|
ma.src = ArtifactLocation(finishingBattle->loserHero->id, artSlot.first);
|
||||||
const CArtifactInstance * art = ma.src.getArt();
|
ma.src.creature = finishingBattle->loserHero->findStack(finishingBattle->loserHero->commander);
|
||||||
|
const auto art = finishingBattle->loserHero->commander->getArt(artSlot.first);
|
||||||
if (art && !art->artType->isBig())
|
if (art && !art->artType->isBig())
|
||||||
{
|
{
|
||||||
sendMoveArtifact(art, &ma);
|
sendMoveArtifact(art, &ma);
|
||||||
|
@ -17,20 +17,6 @@
|
|||||||
#include "../../lib/networkPacks/PacksForServer.h"
|
#include "../../lib/networkPacks/PacksForServer.h"
|
||||||
#include "../../lib/serializer/Cast.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):
|
TimerPauseQuery::TimerPauseQuery(CGameHandler * owner, PlayerColor player):
|
||||||
CQuery(owner)
|
CQuery(owner)
|
||||||
{
|
{
|
||||||
@ -127,12 +113,12 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const
|
|||||||
|
|
||||||
if(auto arts = dynamic_ptr_cast<ExchangeArtifacts>(pack))
|
if(auto arts = dynamic_ptr_cast<ExchangeArtifacts>(pack))
|
||||||
{
|
{
|
||||||
if(auto id1 = std::visit(GetEngagedHeroIds(), arts->src.artHolder))
|
if(auto id1 = arts->src.artHolder)
|
||||||
if(!vstd::contains(ourIds, *id1))
|
if(!vstd::contains(ourIds, id1))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
if(auto id2 = std::visit(GetEngagedHeroIds(), arts->dst.artHolder))
|
if(auto id2 = arts->dst.artHolder)
|
||||||
if(!vstd::contains(ourIds, *id2))
|
if(!vstd::contains(ourIds, id2))
|
||||||
return true;
|
return true;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
@ -144,8 +130,8 @@ bool CGarrisonDialogQuery::blocksPack(const CPack * pack) const
|
|||||||
|
|
||||||
if(auto art = dynamic_ptr_cast<EraseArtifactByClient>(pack))
|
if(auto art = dynamic_ptr_cast<EraseArtifactByClient>(pack))
|
||||||
{
|
{
|
||||||
if (auto id = std::visit(GetEngagedHeroIds(), art->al.artHolder))
|
if(auto id = art->al.artHolder)
|
||||||
return !vstd::contains(ourIds, *id);
|
return !vstd::contains(ourIds, id);
|
||||||
}
|
}
|
||||||
|
|
||||||
if(auto dismiss = dynamic_ptr_cast<AssembleArtifacts>(pack))
|
if(auto dismiss = dynamic_ptr_cast<AssembleArtifacts>(pack))
|
||||||
|
@ -240,7 +240,7 @@ TEST_F(CGameStateTest, issue2765)
|
|||||||
gameCallback->sendAndApply(&na);
|
gameCallback->sendAndApply(&na);
|
||||||
|
|
||||||
PutArtifact pack;
|
PutArtifact pack;
|
||||||
pack.al = ArtifactLocation(defender, ArtifactPosition::MACH1);
|
pack.al = ArtifactLocation(defender->id, ArtifactPosition::MACH1);
|
||||||
pack.art = a;
|
pack.art = a;
|
||||||
gameCallback->sendAndApply(&pack);
|
gameCallback->sendAndApply(&pack);
|
||||||
}
|
}
|
||||||
@ -334,7 +334,7 @@ TEST_F(CGameStateTest, battleResurrection)
|
|||||||
gameCallback->sendAndApply(&na);
|
gameCallback->sendAndApply(&na);
|
||||||
|
|
||||||
PutArtifact pack;
|
PutArtifact pack;
|
||||||
pack.al = ArtifactLocation(attacker, ArtifactPosition::SPELLBOOK);
|
pack.al = ArtifactLocation(attacker->id, ArtifactPosition::SPELLBOOK);
|
||||||
pack.art = a;
|
pack.art = a;
|
||||||
gameCallback->sendAndApply(&pack);
|
gameCallback->sendAndApply(&pack);
|
||||||
}
|
}
|
||||||
|
Reference in New Issue
Block a user