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:
parent
6ee4fd24f7
commit
72122fb433
@ -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();
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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()
|
||||
|
@ -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();
|
||||
|
@ -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:
|
||||
|
@ -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));
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user