From 07c811dd67a2efc3b86ab4a636016682f4c731b2 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Sun, 18 Jun 2023 15:21:35 +0300 Subject: [PATCH] CCombinedArtifactInstance refactoring --- client/widgets/CArtifactsOfHeroAltar.cpp | 9 +-- lib/ArtifactUtils.cpp | 30 ++++---- lib/CArtHandler.cpp | 94 +++++++----------------- lib/CArtHandler.h | 84 +++++++++------------ lib/NetPacksLib.cpp | 33 +++++---- lib/mapObjects/CQuest.cpp | 4 +- lib/registerTypes/RegisterTypes.h | 1 - server/CGameHandler.cpp | 9 +-- 8 files changed, 99 insertions(+), 165 deletions(-) diff --git a/client/widgets/CArtifactsOfHeroAltar.cpp b/client/widgets/CArtifactsOfHeroAltar.cpp index b7cfa150c..b12e3abdf 100644 --- a/client/widgets/CArtifactsOfHeroAltar.cpp +++ b/client/widgets/CArtifactsOfHeroAltar.cpp @@ -98,13 +98,10 @@ void CArtifactsOfHeroAltar::deleteFromVisible(const CArtifactInstance * artInst) } else { - if(artInst->canBeDisassembled()) + for(const auto & part : artInst->partsInfo) { - for(const auto & part : dynamic_cast(artInst)->constituentsInfo) - { - if(part.slot != ArtifactPosition::PRE_FIRST) - getArtPlace(part.slot)->setArtifact(nullptr); - } + if(part.slot != ArtifactPosition::PRE_FIRST) + getArtPlace(part.slot)->setArtifact(nullptr); } } } \ No newline at end of file diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index fcc5fe95f..4619140cc 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -165,24 +165,23 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createScroll(const SpellID & sid) DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifact * art) { + assert(art); + + auto * artInst = new CArtifactInstance(art); if(art->canBeDisassembled()) { - auto * ret = new CCombinedArtifactInstance(art); - ret->createConstituents(); - return ret; + assert(art->constituents); + for(const auto & part : *art->constituents) + artInst->addArtInstAsPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST); } - else + if(dynamic_cast(art)) { - auto * ret = new CArtifactInstance(art); - if(dynamic_cast(art)) - { - auto bonus = std::make_shared(); - bonus->type = BonusType::LEVEL_COUNTER; - bonus->val = 0; - ret->addNewBonus(bonus); - } - return ret; + auto bonus = std::make_shared(); + bonus->type = BonusType::LEVEL_COUNTER; + bonus->val = 0; + artInst->addNewBonus(bonus); } + return artInst; } DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(const ArtifactID & aid) @@ -211,10 +210,9 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const map->addNewArtifactInstance(art); if(art->artType && art->canBeDisassembled()) { - auto * combined = dynamic_cast(art); - for(CCombinedArtifactInstance::ConstituentInfo & ci : combined->constituentsInfo) + for(auto & part : art->partsInfo) { - map->addNewArtifactInstance(ci.art); + map->addNewArtifactInstance(part.art); } } return art; diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 524169629..024f45786 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -854,6 +854,11 @@ void CArtifactInstance::putAt(const ArtifactLocation & al) void CArtifactInstance::removeFrom(const ArtifactLocation & al) { al.getHolderArtSet()->removeArtifact(al.slot); + for(auto & part : partsInfo) + { + if(part.slot != ArtifactPosition::PRE_FIRST) + part.slot = ArtifactPosition::PRE_FIRST; + } } bool CArtifactInstance::canBeDisassembled() const @@ -870,6 +875,8 @@ void CArtifactInstance::move(const ArtifactLocation & src, const ArtifactLocatio void CArtifactInstance::deserializationFix() { setType(artType); + for(PartInfo & part : partsInfo) + attachTo(*part.art); } SpellID CArtifactInstance::getScrollSpellID() const @@ -885,74 +892,28 @@ SpellID CArtifactInstance::getScrollSpellID() const bool CArtifactInstance::isPart(const CArtifactInstance *supposedPart) const { - return supposedPart == this; -} - -CCombinedArtifactInstance::CCombinedArtifactInstance(CArtifact *Art) - : CArtifactInstance(Art) //TODO: seems unused, but need to be written -{ -} - -void CCombinedArtifactInstance::createConstituents() -{ - assert(artType); - assert(artType->constituents); - - for(const CArtifact * art : *artType->constituents) - { - addAsConstituent(ArtifactUtils::createNewArtifactInstance(art->getId()), ArtifactPosition::PRE_FIRST); - } -} - -void CCombinedArtifactInstance::addAsConstituent(CArtifactInstance * art, const ArtifactPosition & slot) -{ - assert(vstd::contains_if(*artType->constituents, [=](const CArtifact * constituent){ - return constituent->getId() == art->artType->getId(); - })); - assert(art->getParentNodes().size() == 1 && art->getParentNodes().front() == art->artType); - constituentsInfo.emplace_back(art, slot); - attachTo(*art); -} - -void CCombinedArtifactInstance::removeFrom(const ArtifactLocation & al) -{ - CArtifactInstance::removeFrom(al); - for(auto & part : constituentsInfo) - { - if(part.slot != ArtifactPosition::PRE_FIRST) - part.slot = ArtifactPosition::PRE_FIRST; - } -} - -void CCombinedArtifactInstance::deserializationFix() -{ - for(ConstituentInfo &ci : constituentsInfo) - attachTo(*ci.art); -} - -bool CCombinedArtifactInstance::isPart(const CArtifactInstance *supposedPart) const -{ - bool me = CArtifactInstance::isPart(supposedPart); - if(me) + if(supposedPart == this) return true; //check for constituents - for(const ConstituentInfo &constituent : constituentsInfo) + for(const PartInfo & constituent : partsInfo) if(constituent.art == supposedPart) return true; return false; } -CCombinedArtifactInstance::ConstituentInfo::ConstituentInfo(CArtifactInstance * Art, const ArtifactPosition & Slot): - art(Art), - slot(Slot) +void CCombinedArtifactInstance::addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & slot) { -} - -bool CCombinedArtifactInstance::ConstituentInfo::operator==(const ConstituentInfo &rhs) const -{ - return art == rhs.art && slot == rhs.slot; + auto artInst = static_cast(this); + assert(vstd::contains_if(*artInst->artType->constituents, + [=](const CArtifact * partType) + { + return partType->getId() == art->getTypeId(); + })); + assert(art->getParentNodes().size() == 1 && art->getParentNodes().front() == art->artType); + partsInfo.emplace_back(art, slot); + artInst->attachTo(*art); } CArtifactSet::~CArtifactSet() = default; @@ -1090,8 +1051,7 @@ void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art) if(art->artType->canBeDisassembled() && ArtifactUtils::isSlotEquipment(slot)) { const CArtifactInstance * mainPart = nullptr; - auto & parts = dynamic_cast(art)->constituentsInfo; - for(const auto & part : parts) + for(const auto & part : art->partsInfo) if(vstd::contains(part.art->artType->possibleSlots.at(bearerType()), slot) && (part.slot == ArtifactPosition::PRE_FIRST)) { @@ -1099,7 +1059,7 @@ void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art) break; } - for(auto & part : parts) + for(auto & part : art->partsInfo) { if(part.art != mainPart) { @@ -1120,8 +1080,7 @@ void CArtifactSet::removeArtifact(ArtifactPosition slot) { if(art->canBeDisassembled()) { - auto combinedArt = dynamic_cast(art); - for(auto & part : combinedArt->constituentsInfo) + for(auto & part : art->partsInfo) { if(getArt(part.slot, false)) eraseArtSlot(part.slot); @@ -1131,19 +1090,18 @@ void CArtifactSet::removeArtifact(ArtifactPosition slot) } } -std::pair CArtifactSet::searchForConstituent(const ArtifactID & aid) const +std::pair CArtifactSet::searchForConstituent(const ArtifactID & aid) const { for(const auto & slot : artifactsInBackpack) { auto art = slot.artifact; if(art->canBeDisassembled()) { - auto * ass = dynamic_cast(art.get()); - for(auto& ci : ass->constituentsInfo) + for(auto& ci : art->partsInfo) { if(ci.art->getTypeId() == aid) { - return {ass, ci.art}; + return {art, ci.art}; } } } @@ -1156,7 +1114,7 @@ const CArtifactInstance * CArtifactSet::getHiddenArt(const ArtifactID & aid) con return searchForConstituent(aid).second; } -const CCombinedArtifactInstance * CArtifactSet::getAssemblyByConstituent(const ArtifactID & aid) const +const CArtifactInstance * CArtifactSet::getAssemblyByConstituent(const ArtifactID & aid) const { return searchForConstituent(aid).first; } diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 76f10930a..820d5fb95 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -137,12 +137,33 @@ public: } }; -class DLL_LINKAGE CArtifactInstance : public CBonusSystemNode +class CCombinedArtifactInstance +{ +protected: + CCombinedArtifactInstance() = default; +public: + struct PartInfo + { + ConstTransitivePtr art; + ArtifactPosition slot; + template void serialize(Handler & h, const int version) + { + h & art; + h & slot; + } + PartInfo(CArtifactInstance * art = nullptr, const ArtifactPosition & slot = ArtifactPosition::PRE_FIRST) + : art(art), slot(slot) {}; + }; + std::vector partsInfo; + void addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & slot); +}; + +class DLL_LINKAGE CArtifactInstance : public CBonusSystemNode, public CCombinedArtifactInstance { protected: void init(); public: - CArtifactInstance(CArtifact * Art); + CArtifactInstance(CArtifact * art); CArtifactInstance(); ConstTransitivePtr artType; @@ -150,66 +171,27 @@ public: std::string nodeName() const override; void deserializationFix(); - void setType(CArtifact *Art); + void setType(CArtifact * art); std::string getDescription() const; SpellID getScrollSpellID() const; //to be used with scrolls (and similar arts), -1 if none ArtifactID getTypeId() const; - bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const; //forwards to the above one - virtual bool canBeDisassembled() const; + bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const; + bool canBeDisassembled() const; /// Checks if this a part of this artifact: artifact instance is a part /// of itself, additionally truth is returned for constituents of combined arts - virtual bool isPart(const CArtifactInstance *supposedPart) const; - - virtual void putAt(const ArtifactLocation & al); - virtual void removeFrom(const ArtifactLocation & al); - virtual void move(const ArtifactLocation & src, const ArtifactLocation & dst); + bool isPart(const CArtifactInstance * supposedPart) const; + void putAt(const ArtifactLocation & al); + void removeFrom(const ArtifactLocation & al); + void move(const ArtifactLocation & src, const ArtifactLocation & dst); template void serialize(Handler &h, const int version) { h & static_cast(*this); h & artType; h & id; - BONUS_TREE_DESERIALIZATION_FIX - } -}; - -class DLL_LINKAGE CCombinedArtifactInstance : public CArtifactInstance -{ -public: - CCombinedArtifactInstance(CArtifact * Art); - struct ConstituentInfo - { - ConstTransitivePtr art; - ArtifactPosition slot; - template void serialize(Handler &h, const int version) - { - h & art; - h & slot; - } - - bool operator==(const ConstituentInfo &rhs) const; - ConstituentInfo(CArtifactInstance * art = nullptr, const ArtifactPosition & slot = ArtifactPosition::PRE_FIRST); - }; - - std::vector constituentsInfo; - - bool isPart(const CArtifactInstance *supposedPart) const override; - void createConstituents(); - void addAsConstituent(CArtifactInstance * art, const ArtifactPosition & slot); - void removeFrom(const ArtifactLocation & al) override; - - CCombinedArtifactInstance() = default; - - void deserializationFix(); - - friend class CArtifactInstance; - friend struct AssembledArtifact; - template void serialize(Handler &h, const int version) - { - h & static_cast(*this); - h & constituentsInfo; + h & partsInfo; BONUS_TREE_DESERIALIZATION_FIX } }; @@ -313,7 +295,7 @@ public: const ArtifactPosition getSlotByInstance(const CArtifactInstance * artInst) const; /// Search for constituents of assemblies in backpack which do not have an ArtifactPosition const CArtifactInstance * getHiddenArt(const ArtifactID & aid) const; - const CCombinedArtifactInstance * getAssemblyByConstituent(const ArtifactID & aid) const; + const CArtifactInstance * getAssemblyByConstituent(const ArtifactID & aid) const; /// Checks if hero possess artifact of given id (either in backack or worn) bool hasArt(const ArtifactID & aid, bool onlyWorn = false, bool searchBackpackAssemblies = false, bool allowLocked = true) const; bool hasArtBackpack(const ArtifactID & aid) const; @@ -335,7 +317,7 @@ public: void serializeJsonArtifacts(JsonSerializeFormat & handler, const std::string & fieldName, CMap * map); protected: - std::pair searchForConstituent(const ArtifactID & aid) const; + std::pair searchForConstituent(const ArtifactID & aid) const; private: void serializeJsonHero(JsonSerializeFormat & handler, CMap * map); diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 55517dafd..a235e5651 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1524,12 +1524,17 @@ void NewObject::applyGs(CGameState *gs) void NewArtifact::applyGs(CGameState *gs) { assert(!vstd::contains(gs->map->artInstances, art)); - gs->map->addNewArtifactInstance(art); - assert(!art->getParentNodes().size()); + assert(art->artType); + art->setType(art->artType); - if(auto * cart = dynamic_cast(art.get())) - cart->createConstituents(); + if(art->canBeDisassembled()) + { + assert(art->artType->constituents); + for(const auto & part : *art->artType->constituents) + art->addArtInstAsPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST); + } + gs->map->addNewArtifactInstance(art); } const CStackInstance * StackLocation::getStack() @@ -1930,7 +1935,7 @@ void AssembledArtifact::applyGs(CGameState *gs) return art->getId() == builtArt->getId(); })); - auto * combinedArt = new CCombinedArtifactInstance(builtArt); + auto * combinedArt = new CArtifactInstance(builtArt); gs->map->addNewArtifactInstance(combinedArt); // Retrieve all constituents for(const CArtifact * constituent : *builtArt->constituents) @@ -1955,7 +1960,7 @@ void AssembledArtifact::applyGs(CGameState *gs) al.slot = std::min(al.slot, pos); pos = ArtifactPosition::PRE_FIRST; } - combinedArt->addAsConstituent(constituentInstance, pos); + combinedArt->addArtInstAsPart(constituentInstance, pos); } //put new combined artifacts @@ -1964,19 +1969,19 @@ void AssembledArtifact::applyGs(CGameState *gs) void DisassembledArtifact::applyGs(CGameState *gs) { - auto * disassembled = dynamic_cast(al.getArt()); + auto * disassembled = al.getArt(); assert(disassembled); - std::vector constituents = disassembled->constituentsInfo; + auto parts = disassembled->partsInfo; disassembled->removeFrom(al); - for(CCombinedArtifactInstance::ConstituentInfo &ci : constituents) + for(auto & part : parts) { - ArtifactLocation constituentLoc = al; - constituentLoc.slot = (ci.slot >= 0 ? ci.slot : al.slot); //-1 is slot of main constituent -> it'll replace combined artifact in its pos - disassembled->detachFrom(*ci.art); - ci.art->putAt(constituentLoc); + ArtifactLocation partLoc = al; + // 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); + disassembled->detachFrom(*part.art); + part.art->putAt(partLoc); } - gs->map->eraseArtifactInstance(disassembled); } diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 563970129..01812d0d9 100644 --- a/lib/mapObjects/CQuest.cpp +++ b/lib/mapObjects/CQuest.cpp @@ -153,7 +153,7 @@ bool CQuest::checkQuest(const CGHeroInstance * h) const if(h->getArtPosCount(elem.first, false, true, true) < elem.second) return false; if(!h->hasArt(elem.first)) - reqSlots += h->getAssemblyByConstituent(elem.first)->constituentsInfo.size() - 2; + reqSlots += h->getAssemblyByConstituent(elem.first)->partsInfo.size() - 2; } if(ArtifactUtils::isBackpackFreeSlots(h, reqSlots)) return true; @@ -804,7 +804,7 @@ void CGSeerHut::finishQuest(const CGHeroInstance * h, ui32 accept) const { const auto * assembly = h->getAssemblyByConstituent(elem); assert(assembly); - auto parts = assembly->constituentsInfo; + auto parts = assembly->partsInfo; // Remove the assembly cb->removeArtifact(ArtifactLocation(h, h->getArtPos(assembly))); diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index 081a3b50e..405c9bbab 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -218,7 +218,6 @@ void registerTypesMapObjects2(Serializer &s) s.template registerType(); //s.template registerType(); s.template registerType(); - s.template registerType(); //s.template registerType(); s.template registerType(); diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index b26b0abd2..1093c2e65 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -6806,17 +6806,12 @@ bool CGameHandler::giveHeroNewArtifact(const CGHeroInstance * h, const CArtifact COMPLAIN_RET_FALSE_IF(!artType->canBePutAt(h, pos, false), "Cannot put artifact in that slot!"); } - CArtifactInstance * newArtInst = nullptr; - if(artType->canBeDisassembled()) - newArtInst = new CCombinedArtifactInstance(); - else - newArtInst = new CArtifactInstance(); - + auto * newArtInst = new CArtifactInstance(); newArtInst->artType = artType; // *NOT* via settype -> all bonus-related stuff must be done by NewArtifact apply NewArtifact na; na.art = newArtInst; - sendAndApply(&na); // -> updates a!!!, will create a on other machines + sendAndApply(&na); // -> updates newArtInst!!! if(giveHeroArtifact(h, newArtInst, pos)) return true;