1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-05-13 22:06:58 +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

View File

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

View File

@ -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()));
return;
}
auto art = dynamic_cast<const CArtifact*>(artifactID.toArtifact(CGI->artifacts()));
auto art = artifactID.toArtifact();
int price = art->getPrice();
bool possible = LOCPLINT->cb->getResourceAmount(Res::GOLD) >= price;

View File

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

View File

@ -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()
{
setNodeType(ARTIFACT);
@ -800,15 +865,12 @@ std::string CArtifactInstance::getEffectiveDescription(const CGHeroInstance * he
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()))
{
if(canBePutAt(h, slot)) //if(artType->fitsAt(h->artifWorn, slot))
{
//we've found a free suitable slot.
if(artType->canBePutAt(h, slot))
return slot;
}
}
//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
{
return 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);
return artType->canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved);
}
void CArtifactInstance::putAt(ArtifactLocation al)
@ -876,7 +909,7 @@ void CArtifactInstance::removeFrom(ArtifactLocation al)
bool CArtifactInstance::canBeDisassembled() const
{
return bool(artType->constituents);
return artType->canBeDisassembled();
}
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;
}
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)
: 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)
{
auto * artifact = CArtifactInstance::createArtifact(map, artifactID.toEnum());
auto slot = ArtifactPosition(GameConstants::BACKPACK_START + static_cast<si32>(artifactsInBackpack.size()));
if(artifact->canBePutAt(this, slot))
auto slot = ArtifactPosition(GameConstants::BACKPACK_START + (si32)artifactsInBackpack.size());
if(artifact->artType->canBePutAt(this, slot))
putArtifact(slot, artifact);
}
}
@ -1517,7 +1503,7 @@ void CArtifactSet::serializeJsonSlot(JsonSerializeFormat & handler, const Artifa
{
auto * artifact = CArtifactInstance::createArtifact(map, artifactID.toEnum());
if(artifact->canBePutAt(this, slot))
if(artifact->artType->canBePutAt(this, slot))
{
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
{
return this->Bearer;
}
DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition(const CArtifactInstance * artifact,
const CArtifactSet * target)
DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtifactDstPosition(const ArtifactID & aid, 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);
if((!existingArtInfo || !existingArtInfo->locked)
&& artifact->canBePutAt(target, slot))
&& art->canBePutAt(target, slot))
{
return slot;
}
}
return ArtifactPosition(GameConstants::BACKPACK_START);
return GameConstants::BACKPACK_START;
}
DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & ArtifactUtils::unmovableSlots()

View File

@ -90,6 +90,8 @@ public:
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 serializeJson(JsonSerializeFormat & handler);
@ -155,7 +157,6 @@ public:
ArtifactPosition firstBackpackSlot(const CArtifactSet *h) const;
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
virtual bool canBeDisassembled() const;
virtual void putAt(ArtifactLocation al);
@ -209,8 +210,6 @@ public:
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 removeFrom(ArtifactLocation al) override;
bool isPart(const CArtifactInstance *supposedPart) const override;
@ -371,6 +370,7 @@ class DLL_LINKAGE CArtifactFittingSet : public CArtifactSet
public:
CArtifactFittingSet(ArtBearer::ArtBearer Bearer);
void putArtifact(ArtifactPosition pos, CArtifactInstance * art) override;
void removeArtifact(ArtifactPosition pos);
ArtBearer::ArtBearer bearerType() const override;
protected:
@ -380,8 +380,7 @@ protected:
namespace ArtifactUtils
{
// Calculates where an artifact gets placed when it gets transferred from one hero to another.
DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const CArtifactInstance * artifact,
const CArtifactSet * target);
DLL_LINKAGE ArtifactPosition getArtifactDstPosition(const ArtifactID & aid, const CArtifactSet * target);
// TODO: Make this constexpr when the toolset is upgraded
DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & unmovableSlots();
DLL_LINKAGE const std::vector<ArtifactPosition::EArtifactPosition> & constituentWornSlots();

View File

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

View File

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