1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-27 22:47:48 +02:00

CArtifact, CArtifactInstance, CCombinedArtifactInstance reorganization

This commit is contained in:
SoundSSGood 2023-03-13 12:28:33 +02:00
parent 6ee4fd24f7
commit 72122fb433
7 changed files with 110 additions and 101 deletions

@ -633,7 +633,7 @@ CArtifactsOfHero::~CArtifactsOfHero()
if(!curHero->artifactsTransitionPos.empty()) if(!curHero->artifactsTransitionPos.empty())
{ {
auto artPlace = getArtPlace( auto artPlace = getArtPlace(
ArtifactUtils::getArtifactDstPosition(curHero->artifactsTransitionPos.begin()->artifact, curHero)); ArtifactUtils::getArtifactDstPosition(curHero->artifactsTransitionPos.begin()->artifact->artType->getId(), curHero));
assert(artPlace); assert(artPlace);
assert(artPlace->ourOwner); assert(artPlace->ourOwner);
artPlace->setMeAsDest(); artPlace->setMeAsDest();

@ -805,7 +805,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID)
LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(BuildingID::BLACKSMITH)->second->getNameTranslated())); LOCPLINT->showInfoDialog(boost::str(boost::format(CGI->generaltexth->allTexts[273]) % town->town->buildings.find(BuildingID::BLACKSMITH)->second->getNameTranslated()));
return; return;
} }
auto art = dynamic_cast<const CArtifact*>(artifactID.toArtifact(CGI->artifacts())); auto art = artifactID.toArtifact();
int price = art->getPrice(); int price = art->getPrice();
bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price; bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price;

@ -843,7 +843,7 @@ void CExchangeController::moveArtifact(
{ {
auto srcLocation = ArtifactLocation(source, srcPosition); auto srcLocation = ArtifactLocation(source, srcPosition);
auto dstLocation = ArtifactLocation(target, auto dstLocation = ArtifactLocation(target,
ArtifactUtils::getArtifactDstPosition(source->getArt(srcPosition), target)); ArtifactUtils::getArtifactDstPosition(source->getArt(srcPosition)->artType->getId(), target));
cb->swapArtifacts(srcLocation, dstLocation); cb->swapArtifacts(srcLocation, dstLocation);
} }

@ -139,6 +139,71 @@ bool CArtifact::isTradable() const
} }
} }
bool CArtifact::canBeDisassembled() const
{
return !(constituents == nullptr);
}
bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const
{
if(slot == ArtifactPosition::TRANSITION_POS)
return true;
auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool
{
if(ArtifactUtils::isSlotBackpack(slot))
{
if(isBig())
return false;
//TODO backpack limit
return true;
}
auto bearerPossibleSlots = possibleSlots.at(artSet->bearerType());
if(bearerPossibleSlots.empty())
{
logMod->warn("Warning: artifact %s doesn't have defined allowed slots for bearer of type %s", getNameTranslated(), artSet->bearerType());
return false;
}
if(!vstd::contains(bearerPossibleSlots, slot))
return false;
return artSet->isPositionFree(slot, assumeDestRemoved);
};
if(canBeDisassembled())
{
if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved))
return false;
if(ArtifactUtils::isSlotBackpack(slot))
return true; //TODO backpack limit
CArtifactFittingSet fittingSet(artSet->bearerType());
fittingSet.artifactsWorn = artSet->artifactsWorn;
if(assumeDestRemoved)
fittingSet.removeArtifact(slot);
assert(constituents);
for(const auto art : *constituents)
{
auto possibleSlot = ArtifactUtils::getArtifactDstPosition(art->getId(), &fittingSet);
if(ArtifactUtils::isSlotEquipment(possibleSlot))
{
fittingSet.setNewArtSlot(possibleSlot, nullptr, true);
}
else
{
return false;
}
}
return true;
}
else
{
return simpleArtCanBePutAt(artSet, slot, assumeDestRemoved);
}
}
CArtifact::CArtifact() CArtifact::CArtifact()
{ {
setNodeType(ARTIFACT); setNodeType(ARTIFACT);
@ -800,15 +865,12 @@ std::string CArtifactInstance::getEffectiveDescription(const CGHeroInstance * he
return text; return text;
} }
ArtifactPosition CArtifactInstance::firstAvailableSlot(const CArtifactSet *h) const ArtifactPosition CArtifactInstance::firstAvailableSlot(const CArtifactSet * h) const
{ {
for(const auto & slot : artType->possibleSlots.at(h->bearerType())) for(const auto & slot : artType->possibleSlots.at(h->bearerType()))
{ {
if(canBePutAt(h, slot)) //if(artType->fitsAt(h->artifWorn, slot)) if(artType->canBePutAt(h, slot))
{
//we've found a free suitable slot.
return slot; return slot;
}
} }
//if haven't find proper slot, use backpack //if haven't find proper slot, use backpack
@ -825,36 +887,7 @@ ArtifactPosition CArtifactInstance::firstBackpackSlot(const CArtifactSet *h) con
bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved) const bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved) const
{ {
return canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved); return artType->canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved);
}
bool CArtifactInstance::canBePutAt(const CArtifactSet *artSet, ArtifactPosition slot, bool assumeDestRemoved) const
{
if(slot == ArtifactPosition::TRANSITION_POS)
{
return true;
}
if(ArtifactUtils::isSlotBackpack(slot))
{
if(artType->isBig())
return false;
//TODO backpack limit
return true;
}
auto possibleSlots = artType->possibleSlots.find(artSet->bearerType());
if(possibleSlots == artType->possibleSlots.end())
{
logMod->warn("Warning: artifact %s doesn't have defined allowed slots for bearer of type %s", artType->getNameTranslated(), artSet->bearerType());
return false;
}
if(!vstd::contains(possibleSlots->second, slot))
return false;
return artSet->isPositionFree(slot, assumeDestRemoved);
} }
void CArtifactInstance::putAt(ArtifactLocation al) void CArtifactInstance::putAt(ArtifactLocation al)
@ -876,7 +909,7 @@ void CArtifactInstance::removeFrom(ArtifactLocation al)
bool CArtifactInstance::canBeDisassembled() const bool CArtifactInstance::canBeDisassembled() const
{ {
return bool(artType->constituents); return artType->canBeDisassembled();
} }
std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CArtifactSet * h, bool equipped) const std::vector<const CArtifact *> CArtifactInstance::assemblyPossibilities(const CArtifactSet * h, bool equipped) const
@ -1007,53 +1040,6 @@ bool CArtifactInstance::isPart(const CArtifactInstance *supposedPart) const
return supposedPart == this; return supposedPart == this;
} }
bool CCombinedArtifactInstance::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const
{
if(slot == ArtifactPosition::TRANSITION_POS)
return true;
if(!CArtifactInstance::canBePutAt(artSet, slot, assumeDestRemoved))
return false;
if(ArtifactUtils::isSlotBackpack(slot))
return true; //we can always remove combined art to the backapck
CArtifactFittingSet fittingSet(artSet->bearerType());
fittingSet.artifactsWorn = artSet->artifactsWorn;
auto artToRemove = fittingSet.getArt(slot);
if(assumeDestRemoved && artToRemove)
{
if(artToRemove->canBeDisassembled())
{
auto combinedArtToRemove = dynamic_cast<CCombinedArtifactInstance*>(artToRemove);
for(auto & part : combinedArtToRemove->constituentsInfo)
{
if(ArtifactUtils::isSlotEquipment(part.slot))
{
fittingSet.eraseArtSlot(part.slot);
}
}
}
fittingSet.eraseArtSlot(slot);
}
for(auto & art : constituentsInfo)
{
auto possibleSlot = art.art->firstAvailableSlot(&fittingSet);
if(ArtifactUtils::isSlotEquipment(possibleSlot))
{
fittingSet.setNewArtSlot(possibleSlot, nullptr, true);
}
else
{
return false;
}
}
return true;
}
bool CCombinedArtifactInstance::canBeDisassembled() const
{
return true;
}
CCombinedArtifactInstance::CCombinedArtifactInstance(CArtifact *Art) CCombinedArtifactInstance::CCombinedArtifactInstance(CArtifact *Art)
: CArtifactInstance(Art) //TODO: seems unused, but need to be written : CArtifactInstance(Art) //TODO: seems unused, but need to be written
{ {
@ -1478,8 +1464,8 @@ void CArtifactSet::serializeJsonHero(JsonSerializeFormat & handler, CMap * map)
for(const ArtifactID & artifactID : backpackTemp) for(const ArtifactID & artifactID : backpackTemp)
{ {
auto * artifact = CArtifactInstance::createArtifact(map, artifactID.toEnum()); auto * artifact = CArtifactInstance::createArtifact(map, artifactID.toEnum());
auto slot = ArtifactPosition(GameConstants::BACKPACK_START + static_cast<si32>(artifactsInBackpack.size())); auto slot = ArtifactPosition(GameConstants::BACKPACK_START + (si32)artifactsInBackpack.size());
if(artifact->canBePutAt(this, slot)) if(artifact->artType->canBePutAt(this, slot))
putArtifact(slot, artifact); putArtifact(slot, artifact);
} }
} }
@ -1517,7 +1503,7 @@ void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const Artifa
{ {
auto * artifact = CArtifactInstance::createArtifact(map, artifactID.toEnum()); auto * artifact = CArtifactInstance::createArtifact(map, artifactID.toEnum());
if(artifact->canBePutAt(this, slot)) if(artifact->artType->canBePutAt(this, slot))
{ {
putArtifact(slot, artifact); putArtifact(slot, artifact);
} }
@ -1550,25 +1536,45 @@ void CArtifactFittingSet::putArtifact(ArtifactPosition pos, CArtifactInstance *
} }
} }
void CArtifactFittingSet::removeArtifact(ArtifactPosition pos)
{
// Removes the art from the CartifactSet, but does not remove it from art->constituentsInfo.
// removeArtifact is for CArtifactFittingSet only. Do not move it to the parent class.
auto art = getArt(pos);
if(art == nullptr)
return;
if(art->canBeDisassembled())
{
auto combinedArt = dynamic_cast<CCombinedArtifactInstance*>(art);
for(const auto & part : combinedArt->constituentsInfo)
{
if(ArtifactUtils::isSlotEquipment(part.slot))
eraseArtSlot(part.slot);
}
}
eraseArtSlot(pos);
}
ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const ArtBearer::ArtBearer CArtifactFittingSet::bearerType() const
{ {
return this->Bearer; return this->Bearer;
} }
DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition(const CArtifactInstance * artifact, DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition(const ArtifactID & aid, const CArtifactSet * target)
const CArtifactSet * target)
{ {
for(const auto & slot : artifact->artType->possibleSlots.at(target->bearerType())) const auto * art = aid.toArtifact();
for(const auto & slot : art->possibleSlots.at(target->bearerType()))
{ {
const auto * existingArtInfo = target->getSlot(slot); const auto * existingArtInfo = target->getSlot(slot);
if((!existingArtInfo || !existingArtInfo->locked) if((!existingArtInfo || !existingArtInfo->locked)
&& artifact->canBePutAt(target, slot)) && art->canBePutAt(target, slot))
{ {
return slot; return slot;
} }
} }
return ArtifactPosition(GameConstants::BACKPACK_START); return GameConstants::BACKPACK_START;
} }
DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & ArtifactUtils::unmovableSlots() DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & ArtifactUtils::unmovableSlots()

@ -90,6 +90,8 @@ public:
virtual void levelUpArtifact (CArtifactInstance * art){}; virtual void levelUpArtifact (CArtifactInstance * art){};
virtual bool canBeDisassembled() const;
virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const;
void updateFrom(const JsonNode & data); void updateFrom(const JsonNode & data);
void serializeJson(JsonSerializeFormat & handler); void serializeJson(JsonSerializeFormat & handler);
@ -155,7 +157,6 @@ public:
ArtifactPosition firstBackpackSlot(const CArtifactSet *h) const; ArtifactPosition firstBackpackSlot(const CArtifactSet *h) const;
SpellID getGivenSpellID() const; //to be used with scrolls (and similar arts), -1 if none SpellID getGivenSpellID() const; //to be used with scrolls (and similar arts), -1 if none
virtual bool canBePutAt(const CArtifactSet *artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const;
bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const; //forwards to the above one bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const; //forwards to the above one
virtual bool canBeDisassembled() const; virtual bool canBeDisassembled() const;
virtual void putAt(ArtifactLocation al); virtual void putAt(ArtifactLocation al);
@ -209,8 +210,6 @@ public:
std::vector<ConstituentInfo> constituentsInfo; std::vector<ConstituentInfo> constituentsInfo;
bool canBePutAt(const CArtifactSet *artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const override;
bool canBeDisassembled() const override;
void putAt(ArtifactLocation al) override; void putAt(ArtifactLocation al) override;
void removeFrom(ArtifactLocation al) override; void removeFrom(ArtifactLocation al) override;
bool isPart(const CArtifactInstance *supposedPart) const override; bool isPart(const CArtifactInstance *supposedPart) const override;
@ -371,6 +370,7 @@ class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet
public: public:
CArtifactFittingSet(ArtBearer::ArtBearer Bearer); CArtifactFittingSet(ArtBearer::ArtBearer Bearer);
void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override; void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
void removeArtifact(ArtifactPosition pos);
ArtBearer::ArtBearer bearerType() const override; ArtBearer::ArtBearer bearerType() const override;
protected: protected:
@ -380,8 +380,7 @@ protected:
namespace ArtifactUtils namespace ArtifactUtils
{ {
// Calculates where an artifact gets placed when it gets transferred from one hero to another. // Calculates where an artifact gets placed when it gets transferred from one hero to another.
DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const CArtifactInstance * artifact, DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const ArtifactID & aid, const CArtifactSet * target);
const CArtifactSet * target);
// TODO: Make this constexpr when the toolset is upgraded // TODO: Make this constexpr when the toolset is upgraded
DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & unmovableSlots(); DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & unmovableSlots();
DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & constituentWornSlots(); DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & constituentWornSlots();

@ -47,7 +47,6 @@ namespace GameConstants
const int ALL_PLAYERS = 255; //bitfield const int ALL_PLAYERS = 255; //bitfield
const ui16 BACKPACK_START = 19;
const int CREATURES_PER_TOWN = 7; //without upgrades const int CREATURES_PER_TOWN = 7; //without upgrades
const int SPELL_LEVELS = 5; const int SPELL_LEVELS = 5;
const int SPELL_SCHOOL_LEVELS = 4; const int SPELL_SCHOOL_LEVELS = 4;
@ -1044,6 +1043,11 @@ public:
ID_LIKE_OPERATORS(ArtifactPosition, ArtifactPosition::EArtifactPosition) ID_LIKE_OPERATORS(ArtifactPosition, ArtifactPosition::EArtifactPosition)
namespace GameConstants
{
const auto BACKPACK_START = ArtifactPosition::AFTER_LAST;
}
class ArtifactID class ArtifactID
{ {
public: public:

@ -4002,7 +4002,7 @@ bool CGameHandler::bulkMoveArtifacts(ObjectInstanceID srcHero, ObjectInstanceID
std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void std::vector<BulkMoveArtifacts::LinkedSlots> & slots) -> void
{ {
assert(artifact); assert(artifact);
auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact, &artFittingSet); auto dstSlot = ArtifactUtils::getArtifactDstPosition(artifact->artType->getId(), &artFittingSet);
artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact)); artFittingSet.putArtifact(dstSlot, static_cast<ConstTransitivePtr<CArtifactInstance>>(artifact));
slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot)); slots.push_back(BulkMoveArtifacts::LinkedSlots(srcSlot, dstSlot));