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 01/10] 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; From f8023ad28360c00dc1f840c2bffca10aeda01495 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Tue, 20 Jun 2023 20:42:43 +0300 Subject: [PATCH 02/10] CScrollArtifactInstance --- client/widgets/CComponent.cpp | 12 ++++-------- lib/ArtifactUtils.cpp | 15 ++++++++++++++ lib/ArtifactUtils.h | 1 + lib/CArtHandler.cpp | 37 ++++++++++++----------------------- lib/CArtHandler.h | 14 ++++++++++--- 5 files changed, 44 insertions(+), 35 deletions(-) diff --git a/client/widgets/CComponent.cpp b/client/widgets/CComponent.cpp index da1498c31..14b1d1bde 100644 --- a/client/widgets/CComponent.cpp +++ b/client/widgets/CComponent.cpp @@ -169,16 +169,12 @@ std::string CComponent::getDescription() case artifact: { auto artID = ArtifactID(subtype); - std::unique_ptr art; - if (artID != ArtifactID::SPELL_SCROLL) + auto description = VLC->arth->objects[artID]->getDescriptionTranslated(); + if(artID == ArtifactID::SPELL_SCROLL) { - art.reset(ArtifactUtils::createNewArtifactInstance(artID)); + ArtifactUtils::insertScrrollSpellName(description, SpellID(val)); } - else - { - art.reset(ArtifactUtils::createScroll(SpellID(val))); - } - return art->getDescription(); + return description; } case experience: return CGI->generaltexth->allTexts[241]; case spell: return (*CGI->spellh)[subtype]->getDescriptionTranslated(val); diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index 4619140cc..1c356e0f0 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -12,6 +12,7 @@ #include "CArtHandler.h" #include "GameSettings.h" +#include "spells/CSpellHandler.h" #include "mapping/CMap.h" #include "mapObjects/CGHeroInstance.h" @@ -218,4 +219,18 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const return art; } +DLL_LINKAGE void ArtifactUtils::insertScrrollSpellName(std::string & description, SpellID & sid) +{ + // We expect scroll description to be like this: This scroll contains the [spell name] spell which is added + // into spell book for as long as hero carries the scroll. So we want to replace text in [...] with a spell name. + // However other language versions don't have name placeholder at all, so we have to be careful + auto nameStart = description.find_first_of('['); + auto nameEnd = description.find_first_of(']', nameStart); + if(sid.getNum() >= 0) + { + if(nameStart != std::string::npos && nameEnd != std::string::npos) + description = description.replace(nameStart, nameEnd - nameStart + 1, sid.toSpell(VLC->spells())->getNameTranslated()); + } +} + VCMI_LIB_NAMESPACE_END diff --git a/lib/ArtifactUtils.h b/lib/ArtifactUtils.h index 487ce238a..b4feadbe8 100644 --- a/lib/ArtifactUtils.h +++ b/lib/ArtifactUtils.h @@ -41,6 +41,7 @@ namespace ArtifactUtils DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(CArtifact * art); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid); DLL_LINKAGE CArtifactInstance * createArtifact(CMap * map, const ArtifactID & aid, int spellID = -1); + DLL_LINKAGE void insertScrrollSpellName(std::string & description, SpellID & sid); } VCMI_LIB_NAMESPACE_END diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 024f45786..f12356251 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -820,19 +820,7 @@ std::string CArtifactInstance::getDescription() const { std::string text = artType->getDescriptionTranslated(); if(artType->getId() == ArtifactID::SPELL_SCROLL) - { - // we expect scroll description to be like this: This scroll contains the [spell name] spell which is added into your spell book for as long as you carry the scroll. - // so we want to replace text in [...] with a spell name - // however other language versions don't have name placeholder at all, so we have to be careful - SpellID spellID = getScrollSpellID(); - size_t nameStart = text.find_first_of('['); - size_t nameEnd = text.find_first_of(']', nameStart); - if(spellID.getNum() >= 0) - { - if(nameStart != std::string::npos && nameEnd != std::string::npos) - text = text.replace(nameStart, nameEnd - nameStart + 1, spellID.toSpell(VLC->spells())->getNameTranslated()); - } - } + ArtifactUtils::insertScrrollSpellName(text, getScrollSpellID()); return text; } @@ -879,17 +867,6 @@ void CArtifactInstance::deserializationFix() attachTo(*part.art); } -SpellID CArtifactInstance::getScrollSpellID() const -{ - const auto b = getBonusLocalFirst(Selector::type()(BonusType::SPELL)); - if(!b) - { - logMod->warn("Warning: %s doesn't bear any spell!", nodeName()); - return SpellID::NONE; - } - return SpellID(b->subtype); -} - bool CArtifactInstance::isPart(const CArtifactInstance *supposedPart) const { if(supposedPart == this) @@ -916,6 +893,18 @@ void CCombinedArtifactInstance::addArtInstAsPart(CArtifactInstance * art, const artInst->attachTo(*art); } +SpellID CScrollArtifactInstance::getScrollSpellID() const +{ + auto artInst = static_cast(this); + const auto bonus = artInst->getBonusLocalFirst(Selector::type()(BonusType::SPELL)); + if (!bonus) + { + logMod->warn("Warning: %s doesn't bear any spell!", artInst->nodeName()); + return SpellID::NONE; + } + return SpellID(bonus->subtype); +} + CArtifactSet::~CArtifactSet() = default; const CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked) const diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 820d5fb95..99d45c9cc 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -137,7 +137,7 @@ public: } }; -class CCombinedArtifactInstance +class DLL_LINKAGE CCombinedArtifactInstance { protected: CCombinedArtifactInstance() = default; @@ -158,7 +158,16 @@ public: void addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & slot); }; -class DLL_LINKAGE CArtifactInstance : public CBonusSystemNode, public CCombinedArtifactInstance +class DLL_LINKAGE CScrollArtifactInstance +{ +protected: + CScrollArtifactInstance() = default; +public: + SpellID getScrollSpellID() const; +}; + +class DLL_LINKAGE CArtifactInstance + : public CBonusSystemNode, public CCombinedArtifactInstance, public CScrollArtifactInstance { protected: void init(); @@ -174,7 +183,6 @@ public: 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; From 58fc2efd415efb57012cfff4ca750d301051af29 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 22 Jun 2023 00:17:59 +0300 Subject: [PATCH 03/10] CGrowingArtifactInstance --- lib/CArtHandler.cpp | 24 ------------------------ lib/CArtHandler.h | 14 +++++++++----- lib/NetPacksLib.cpp | 2 +- 3 files changed, 10 insertions(+), 30 deletions(-) diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index f12356251..92b9e7a20 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -269,30 +269,6 @@ void CArtifact::serializeJson(JsonSerializeFormat & handler) } -void CGrowingArtifact::levelUpArtifact (CArtifactInstance * art) -{ - auto b = std::make_shared(); - b->type = BonusType::LEVEL_COUNTER; - b->val = 1; - b->duration = BonusDuration::COMMANDER_KILLED; - art->accumulateBonus(b); - - for(const auto & bonus : bonusesPerLevel) - { - if (art->valOfBonuses(BonusType::LEVEL_COUNTER) % bonus.first == 0) //every n levels - { - art->accumulateBonus(std::make_shared(bonus.second)); - } - } - for(const auto & bonus : thresholdBonuses) - { - if (art->valOfBonuses(BonusType::LEVEL_COUNTER) == bonus.first) //every n levels - { - art->addNewBonus(std::make_shared(bonus.second)); - } - } -} - CArtHandler::~CArtHandler() = default; std::vector CArtHandler::loadLegacyData() diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 99d45c9cc..8fa7dc0cb 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -89,8 +89,6 @@ public: std::string nodeName() const override; void addNewBonus(const std::shared_ptr& b) override; - virtual void levelUpArtifact (CArtifactInstance * art){}; - virtual bool canBeDisassembled() const; virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE, bool assumeDestRemoved = false) const; @@ -127,8 +125,6 @@ public: std::vector > bonusesPerLevel; //bonus given each n levels std::vector > thresholdBonuses; //after certain level they will be added once - void levelUpArtifact(CArtifactInstance * art) override; - template void serialize(Handler &h, const int version) { h & static_cast(*this); @@ -166,8 +162,16 @@ public: SpellID getScrollSpellID() const; }; +class DLL_LINKAGE CGrowingArtifactInstance +{ +protected: + CGrowingArtifactInstance() = default; +public: + void growingUp(); +}; + class DLL_LINKAGE CArtifactInstance - : public CBonusSystemNode, public CCombinedArtifactInstance, public CScrollArtifactInstance + : public CBonusSystemNode, public CCombinedArtifactInstance, public CScrollArtifactInstance, public CGrowingArtifactInstance { protected: void init(); diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index a235e5651..8324cab8e 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -2223,7 +2223,7 @@ void BattleResultAccepted::applyGs(CGameState * gs) const { for (auto art : h->commander->artifactsWorn) //increment bonuses for commander artifacts { - art.second.artifact->artType->levelUpArtifact (art.second.artifact); + art.second.artifact->growingUp(); } } } From d44821e733f38507f5c2d2b4915852cdd40a003e Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 22 Jun 2023 17:08:16 +0300 Subject: [PATCH 04/10] CArtifactInstance moved to own file --- client/widgets/CComponent.cpp | 1 + cmake_modules/VCMI_lib.cmake | 2 + lib/CArtHandler.cpp | 122 +------------------------ lib/CArtHandler.h | 77 ---------------- lib/CArtifactInstance.cpp | 166 ++++++++++++++++++++++++++++++++++ lib/CArtifactInstance.h | 91 +++++++++++++++++++ lib/CCreatureSet.h | 1 + 7 files changed, 262 insertions(+), 198 deletions(-) create mode 100644 lib/CArtifactInstance.cpp create mode 100644 lib/CArtifactInstance.h diff --git a/client/widgets/CComponent.cpp b/client/widgets/CComponent.cpp index 14b1d1bde..0db738cd0 100644 --- a/client/widgets/CComponent.cpp +++ b/client/widgets/CComponent.cpp @@ -34,6 +34,7 @@ #include "../../lib/CGeneralTextHandler.h" #include "../../lib/NetPacksBase.h" #include "../../lib/CArtHandler.h" +#include "../../lib/CArtifactInstance.h" CComponent::CComponent(Etype Type, int Subtype, int Val, ESize imageSize, EFonts font): perDay(false) diff --git a/cmake_modules/VCMI_lib.cmake b/cmake_modules/VCMI_lib.cmake index 4cd741a47..f325bfa4f 100644 --- a/cmake_modules/VCMI_lib.cmake +++ b/cmake_modules/VCMI_lib.cmake @@ -220,6 +220,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/BattleFieldHandler.cpp ${MAIN_LIB_DIR}/CAndroidVMHelper.cpp ${MAIN_LIB_DIR}/CArtHandler.cpp + ${MAIN_LIB_DIR}/CArtifactInstance.cpp ${MAIN_LIB_DIR}/CBonusTypeHandler.cpp ${MAIN_LIB_DIR}/CBuildingHandler.cpp ${MAIN_LIB_DIR}/CConfigHandler.cpp @@ -550,6 +551,7 @@ macro(add_main_lib TARGET_NAME LIBRARY_TYPE) ${MAIN_LIB_DIR}/BattleFieldHandler.h ${MAIN_LIB_DIR}/CAndroidVMHelper.h ${MAIN_LIB_DIR}/CArtHandler.h + ${MAIN_LIB_DIR}/CArtifactInstance.h ${MAIN_LIB_DIR}/CBonusTypeHandler.h ${MAIN_LIB_DIR}/CBuildingHandler.h ${MAIN_LIB_DIR}/CConfigHandler.h diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 92b9e7a20..e76b7c0d4 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -15,9 +15,7 @@ #include "CGeneralTextHandler.h" #include "CModHandler.h" #include "GameSettings.h" -#include "spells/CSpellHandler.h" #include "mapObjects/MapObjects.h" -#include "NetPacksBase.h" #include "StringConstants.h" #include "mapObjectConstructors/AObjectTypeHandler.h" @@ -763,129 +761,11 @@ void CArtHandler::afterLoadFinalization() CBonusSystemNode::treeHasChanged(); } -CArtifactInstance::CArtifactInstance() -{ - init(); -} - -CArtifactInstance::CArtifactInstance( CArtifact *Art) -{ - init(); - setType(Art); -} - -void CArtifactInstance::setType( CArtifact *Art ) -{ - artType = Art; - attachTo(*Art); -} - -std::string CArtifactInstance::nodeName() const -{ - return "Artifact instance of " + (artType ? artType->getJsonKey() : std::string("uninitialized")) + " type"; -} - -void CArtifactInstance::init() -{ - id = ArtifactInstanceID(); - id = static_cast(ArtifactID::NONE); //to be randomized - setNodeType(ARTIFACT_INSTANCE); -} - -std::string CArtifactInstance::getDescription() const -{ - std::string text = artType->getDescriptionTranslated(); - if(artType->getId() == ArtifactID::SPELL_SCROLL) - ArtifactUtils::insertScrrollSpellName(text, getScrollSpellID()); - return text; -} - -ArtifactID CArtifactInstance::getTypeId() const -{ - return artType->getId(); -} - -bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved) const -{ - return artType->canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved); -} - -void CArtifactInstance::putAt(const ArtifactLocation & al) -{ - al.getHolderArtSet()->putArtifact(al.slot, this); -} - -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 -{ - return artType->canBeDisassembled(); -} - -void CArtifactInstance::move(const ArtifactLocation & src, const ArtifactLocation & dst) -{ - removeFrom(src); - putAt(dst); -} - -void CArtifactInstance::deserializationFix() -{ - setType(artType); - for(PartInfo & part : partsInfo) - attachTo(*part.art); -} - -bool CArtifactInstance::isPart(const CArtifactInstance *supposedPart) const -{ - if(supposedPart == this) - return true; - - //check for constituents - for(const PartInfo & constituent : partsInfo) - if(constituent.art == supposedPart) - return true; - - return false; -} - -void CCombinedArtifactInstance::addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & 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); -} - -SpellID CScrollArtifactInstance::getScrollSpellID() const -{ - auto artInst = static_cast(this); - const auto bonus = artInst->getBonusLocalFirst(Selector::type()(BonusType::SPELL)); - if (!bonus) - { - logMod->warn("Warning: %s doesn't bear any spell!", artInst->nodeName()); - return SpellID::NONE; - } - return SpellID(bonus->subtype); -} - CArtifactSet::~CArtifactSet() = default; const CArtifactInstance * CArtifactSet::getArt(const ArtifactPosition & pos, bool excludeLocked) const { - if(const ArtSlotInfo *si = getSlot(pos)) + if(const ArtSlotInfo * si = getSlot(pos)) { if(si->artifact && (!excludeLocked || !si->locked)) return si->artifact; diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 8fa7dc0cb..bb2e02516 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -20,9 +20,7 @@ VCMI_LIB_NAMESPACE_BEGIN class CArtHandler; -class CArtifact; class CGHeroInstance; -struct ArtifactLocation; class CArtifactSet; class CArtifactInstance; class CRandomGenerator; @@ -133,81 +131,6 @@ public: } }; -class DLL_LINKAGE 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 CScrollArtifactInstance -{ -protected: - CScrollArtifactInstance() = default; -public: - SpellID getScrollSpellID() const; -}; - -class DLL_LINKAGE CGrowingArtifactInstance -{ -protected: - CGrowingArtifactInstance() = default; -public: - void growingUp(); -}; - -class DLL_LINKAGE CArtifactInstance - : public CBonusSystemNode, public CCombinedArtifactInstance, public CScrollArtifactInstance, public CGrowingArtifactInstance -{ -protected: - void init(); -public: - CArtifactInstance(CArtifact * art); - CArtifactInstance(); - - ConstTransitivePtr artType; - ArtifactInstanceID id; - - std::string nodeName() const override; - void deserializationFix(); - void setType(CArtifact * art); - - std::string getDescription() const; - - ArtifactID getTypeId() 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 - 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; - h & partsInfo; - BONUS_TREE_DESERIALIZATION_FIX - } -}; - class DLL_LINKAGE CArtHandler : public CHandlerBase { public: diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp new file mode 100644 index 000000000..c8dcede34 --- /dev/null +++ b/lib/CArtifactInstance.cpp @@ -0,0 +1,166 @@ +/* + * CArtifactInstance.cpp, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ + +#include "StdInc.h" +#include "CArtifactInstance.h" + +#include "ArtifactUtils.h" +#include "CArtHandler.h" +#include "NetPacksBase.h" + +void CCombinedArtifactInstance::addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & 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); +} + +bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) const +{ + if(supposedPart == this) + return true; + + for(const PartInfo & constituent : partsInfo) + { + if(constituent.art == supposedPart) + return true; + } + + return false; +} + +SpellID CScrollArtifactInstance::getScrollSpellID() const +{ + auto artInst = static_cast(this); + const auto bonus = artInst->getBonusLocalFirst(Selector::type()(BonusType::SPELL)); + if(!bonus) + { + logMod->warn("Warning: %s doesn't bear any spell!", artInst->nodeName()); + return SpellID::NONE; + } + return SpellID(bonus->subtype); +} + +void CGrowingArtifactInstance::growingUp() +{ + auto artInst = static_cast(this); + + if(auto growingArtType = dynamic_cast(static_cast(artInst->artType))) + { + auto bonus = std::make_shared(); + bonus->type = BonusType::LEVEL_COUNTER; + bonus->val = 1; + bonus->duration = BonusDuration::COMMANDER_KILLED; + artInst->accumulateBonus(bonus); + + for(const auto & bonus : growingArtType->bonusesPerLevel) + { + // Every n levels + if(artInst->valOfBonuses(BonusType::LEVEL_COUNTER) % bonus.first == 0) + { + artInst->accumulateBonus(std::make_shared(bonus.second)); + } + } + for(const auto & bonus : growingArtType->thresholdBonuses) + { + // At n level + if(artInst->valOfBonuses(BonusType::LEVEL_COUNTER) == bonus.first) + { + artInst->addNewBonus(std::make_shared(bonus.second)); + } + } + } +} + +void CArtifactInstance::init() +{ + // Artifact to be randomized + id = static_cast(ArtifactID::NONE); + setNodeType(ARTIFACT_INSTANCE); +} + +CArtifactInstance::CArtifactInstance(CArtifact * art) +{ + init(); + setType(art); +} + +CArtifactInstance::CArtifactInstance() +{ + init(); +} + +void CArtifactInstance::setType(CArtifact * art) +{ + artType = art; + attachTo(*art); +} + +std::string CArtifactInstance::nodeName() const +{ + return "Artifact instance of " + (artType ? artType->getJsonKey() : std::string("uninitialized")) + " type"; +} + +std::string CArtifactInstance::getDescription() const +{ + std::string text = artType->getDescriptionTranslated(); + if(artType->getId() == ArtifactID::SPELL_SCROLL) + ArtifactUtils::insertScrrollSpellName(text, getScrollSpellID()); + return text; +} + +ArtifactID CArtifactInstance::getTypeId() const +{ + return artType->getId(); +} + +bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved) const +{ + return artType->canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved); +} + +bool CArtifactInstance::canBeDisassembled() const +{ + return artType->canBeDisassembled(); +} + +void CArtifactInstance::putAt(const ArtifactLocation & al) +{ + al.getHolderArtSet()->putArtifact(al.slot, this); +} + +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; + } +} + +void CArtifactInstance::move(const ArtifactLocation & src, const ArtifactLocation & dst) +{ + removeFrom(src); + putAt(dst); +} + +void CArtifactInstance::deserializationFix() +{ + setType(artType); + for(PartInfo & part : partsInfo) + attachTo(*part.art); +} diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h new file mode 100644 index 000000000..aad5bf1d5 --- /dev/null +++ b/lib/CArtifactInstance.h @@ -0,0 +1,91 @@ +/* + * CArtifactInstance.h, part of VCMI engine + * + * Authors: listed in file AUTHORS in main folder + * + * License: GNU General Public License v2.0 or later + * Full text of license available in license.txt file, in main folder + * + */ +#pragma once + +#include "bonuses/CBonusSystemNode.h" +#include "GameConstants.h" + +VCMI_LIB_NAMESPACE_BEGIN + +struct ArtifactLocation; + +class DLL_LINKAGE 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); + // Checks if supposed part inst is part of this combined art inst + bool isPart(const CArtifactInstance * supposedPart) const; +}; + +class DLL_LINKAGE CScrollArtifactInstance +{ +protected: + CScrollArtifactInstance() = default; +public: + SpellID getScrollSpellID() const; +}; + +class DLL_LINKAGE CGrowingArtifactInstance +{ +protected: + CGrowingArtifactInstance() = default; +public: + void growingUp(); +}; + +class DLL_LINKAGE CArtifactInstance + : public CBonusSystemNode, public CCombinedArtifactInstance, public CScrollArtifactInstance, public CGrowingArtifactInstance +{ +protected: + void init(); +public: + ConstTransitivePtr artType; + ArtifactInstanceID id; + + CArtifactInstance(CArtifact * art); + CArtifactInstance(); + void setType(CArtifact * art); + std::string nodeName() const override; + std::string getDescription() const; + ArtifactID getTypeId() const; + + bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const; + bool canBeDisassembled() const; + void putAt(const ArtifactLocation & al); + void removeFrom(const ArtifactLocation & al); + void move(const ArtifactLocation & src, const ArtifactLocation & dst); + + void deserializationFix(); + template void serialize(Handler & h, const int version) + { + h & static_cast(*this); + h & artType; + h & id; + h & partsInfo; + BONUS_TREE_DESERIALIZATION_FIX + } +}; + +VCMI_LIB_NAMESPACE_END diff --git a/lib/CCreatureSet.h b/lib/CCreatureSet.h index 662fcc9b7..09794f3c8 100644 --- a/lib/CCreatureSet.h +++ b/lib/CCreatureSet.h @@ -13,6 +13,7 @@ #include "bonuses/CBonusSystemNode.h" #include "GameConstants.h" #include "CArtHandler.h" +#include "CArtifactInstance.h" #include "CCreatureHandler.h" #include From 060aecc61c6bb2f4499c5c577ad6910c8a204b40 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Thu, 29 Jun 2023 18:34:07 +0300 Subject: [PATCH 05/10] CArtifact refactoring --- client/widgets/CArtifactHolder.cpp | 2 +- client/widgets/CArtifactsOfHeroBase.cpp | 4 +- lib/ArtifactUtils.cpp | 10 ++-- lib/CArtHandler.cpp | 66 +++++++++++------------ lib/CArtHandler.h | 70 +++++++++++++++++-------- lib/CArtifactInstance.cpp | 13 ++--- lib/CArtifactInstance.h | 9 +++- lib/NetPacksLib.cpp | 8 ++- lib/registerTypes/RegisterTypes.h | 1 - lib/rmg/CMapGenerator.cpp | 2 +- server/CGameHandler.cpp | 2 +- 11 files changed, 110 insertions(+), 77 deletions(-) diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index b2c6a63f7..f2aaf7ee1 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -290,7 +290,7 @@ bool ArtifactUtilsClient::askToDisassemble(const CGHeroInstance * hero, const Ar const auto art = hero->getArt(slot); assert(art); - if(art->canBeDisassembled()) + if(art->isCombined()) { if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->constituents->size() - 1)) return false; diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index be3b94d61..9afe6a20e 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -257,11 +257,11 @@ void CArtifactsOfHeroBase::setSlotData(ArtPlacePtr artPlace, const ArtifactPosit { artPlace->lockSlot(slotInfo->locked); artPlace->setArtifact(slotInfo->artifact); - if(!slotInfo->artifact->canBeDisassembled()) + if(!slotInfo->artifact->isCombined()) { // If the artifact is part of at least one combined artifact, add additional information std::map arts; - for(const auto combinedArt : slotInfo->artifact->artType->constituentOf) + for(const auto combinedArt : slotInfo->artifact->artType->partOf) { arts.insert(std::pair(combinedArt, 0)); for(const auto part : *combinedArt->constituents) diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index 1c356e0f0..32d1b2cf0 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -120,10 +120,10 @@ DLL_LINKAGE std::vector ArtifactUtils::assemblyPossibilities( { std::vector arts; const auto * art = aid.toArtifact(); - if(art->canBeDisassembled()) + if(art->isCombined()) return arts; - for(const auto artifact : art->constituentOf) + for(const auto artifact : art->partOf) { assert(artifact->constituents); bool possible = true; @@ -169,13 +169,13 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa assert(art); auto * artInst = new CArtifactInstance(art); - if(art->canBeDisassembled()) + if(art->isCombined()) { assert(art->constituents); for(const auto & part : *art->constituents) artInst->addArtInstAsPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST); } - if(dynamic_cast(art)) + if(art->isGrowing()) { auto bonus = std::make_shared(); bonus->type = BonusType::LEVEL_COUNTER; @@ -209,7 +209,7 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const art = new CArtifactInstance(); // random, empty } map->addNewArtifactInstance(art); - if(art->artType && art->canBeDisassembled()) + if(art->artType && art->isCombined()) { for(auto & part : art->partsInfo) { diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index e76b7c0d4..b98b7453e 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -46,6 +46,21 @@ VCMI_LIB_NAMESPACE_BEGIN +bool CCombinedArtifact::isCombined() const +{ + return !(constituents == nullptr); +} + +bool CScrollArtifact::isScroll() const +{ + return static_cast(this)->getId() == ArtifactID::SPELL_SCROLL; +} + +bool CGrowingArtifact::isGrowing() const +{ + return !bonusesPerLevel.empty() || !thresholdBonuses.empty(); +} + int32_t CArtifact::getIndex() const { return id.toEnum(); @@ -134,11 +149,6 @@ bool CArtifact::isTradable() const } } -bool CArtifact::canBeDisassembled() const -{ - return !(constituents == nullptr); -} - bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) const { auto simpleArtCanBePutAt = [this](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool @@ -158,7 +168,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b auto artCanBePutAt = [this, simpleArtCanBePutAt](const CArtifactSet * artSet, ArtifactPosition slot, bool assumeDestRemoved) -> bool { - if(canBeDisassembled()) + if(isCombined()) { if(!simpleArtCanBePutAt(artSet, slot, assumeDestRemoved)) return false; @@ -350,17 +360,19 @@ CArtifact * CArtHandler::loadFromJson(const std::string & scope, const JsonNode assert(identifier.find(':') == std::string::npos); assert(!scope.empty()); - CArtifact * art = nullptr; - - if(!VLC->settings()->getBoolean(EGameSettings::MODULE_COMMANDERS) || node["growing"].isNull()) + CArtifact * art = new CArtifact(); + if(!node["growing"].isNull()) { - art = new CArtifact(); - } - else - { - auto * growing = new CGrowingArtifact(); - loadGrowingArt(growing, node); - art = growing; + for(auto bonus : node["growing"]["bonusesPerLevel"].Vector()) + { + art->bonusesPerLevel.emplace_back(static_cast(bonus["level"].Float()), Bonus()); + JsonUtils::parseBonus(bonus["bonus"], &art->bonusesPerLevel.back().second); + } + for(auto bonus : node["growing"]["thresholdBonuses"].Vector()) + { + art->thresholdBonuses.emplace_back(static_cast(bonus["level"].Float()), Bonus()); + JsonUtils::parseBonus(bonus["bonus"], &art->thresholdBonuses.back().second); + } } art->id = ArtifactID(index); art->identifier = identifier; @@ -553,26 +565,12 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node) // when this code is called both combinational art as well as component are loaded // so it is safe to access any of them art->constituents->push_back(objects[id]); - objects[id]->constituentOf.push_back(art); + objects[id]->partOf.push_back(art); }); } } } -void CArtHandler::loadGrowingArt(CGrowingArtifact * art, const JsonNode & node) const -{ - for (auto b : node["growing"]["bonusesPerLevel"].Vector()) - { - art->bonusesPerLevel.emplace_back(static_cast(b["level"].Float()), Bonus()); - JsonUtils::parseBonus(b["bonus"], &art->bonusesPerLevel.back().second); - } - for (auto b : node["growing"]["thresholdBonuses"].Vector()) - { - art->thresholdBonuses.emplace_back(static_cast(b["level"].Float()), Bonus()); - JsonUtils::parseBonus(b["bonus"], &art->thresholdBonuses.back().second); - } -} - ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags, std::function accepts) { auto getAllowedArts = [&](std::vector > &out, std::vector *arts, CArtifact::EartClass flag) @@ -893,7 +891,7 @@ unsigned CArtifactSet::getArtPosCount(const ArtifactID & aid, bool onlyWorn, boo void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art) { setNewArtSlot(slot, art, false); - if(art->artType->canBeDisassembled() && ArtifactUtils::isSlotEquipment(slot)) + if(art->artType->isCombined() && ArtifactUtils::isSlotEquipment(slot)) { const CArtifactInstance * mainPart = nullptr; for(const auto & part : art->partsInfo) @@ -923,7 +921,7 @@ void CArtifactSet::removeArtifact(ArtifactPosition slot) auto art = getArt(slot, false); if(art) { - if(art->canBeDisassembled()) + if(art->isCombined()) { for(auto & part : art->partsInfo) { @@ -940,7 +938,7 @@ std::pair CArtifactSet::se for(const auto & slot : artifactsInBackpack) { auto art = slot.artifact; - if(art->canBeDisassembled()) + if(art->isCombined()) { for(auto& ci : art->partsInfo) { diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index bb2e02516..8254e9f6e 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -42,7 +42,51 @@ namespace ArtBearer }; } -class DLL_LINKAGE CArtifact : public Artifact, public CBonusSystemNode //container for artifacts +class DLL_LINKAGE CCombinedArtifact +{ +protected: + CCombinedArtifact() = default; +public: + std::unique_ptr> constituents; // Artifacts IDs a combined artifact consists of, or nullptr. + std::vector partOf; // Reverse map of constituents - combined arts that include this art + + bool isCombined() const; + + template void serialize(Handler & h, const int version) + { + h & constituents; + h & partOf; + } +}; + +class DLL_LINKAGE CScrollArtifact +{ +protected: + CScrollArtifact() = default; +public: + bool isScroll() const; +}; + +class DLL_LINKAGE CGrowingArtifact +{ +protected: + CGrowingArtifact() = default; +public: + std::vector > bonusesPerLevel; // Bonus given each n levels + std::vector > thresholdBonuses; // After certain level they will be added once + + bool isGrowing() const; + + template void serialize(Handler & h, const int version) + { + h & bonusesPerLevel; + h & thresholdBonuses; + } +}; + +// Container for artifacts. Not for instances. +class DLL_LINKAGE CArtifact + : public Artifact, public CBonusSystemNode, public CCombinedArtifact, public CScrollArtifact, public CGrowingArtifact { ArtifactID id; @@ -58,8 +102,6 @@ public: si32 iconIndex = ArtifactID::NONE; ui32 price = 0; std::map > possibleSlots; //Bearer Type => ids of slots where artifact can be placed - std::unique_ptr > constituents; // Artifacts IDs a combined artifact consists of, or nullptr. - std::vector constituentOf; // Reverse map of constituents - combined arts that include this art EartClass aClass = ART_SPECIAL; CreatureID warMachine; @@ -87,23 +129,22 @@ public: std::string nodeName() const override; void addNewBonus(const std::shared_ptr& b) override; - virtual bool canBeDisassembled() const; virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE, bool assumeDestRemoved = false) const; void updateFrom(const JsonNode & data); void serializeJson(JsonSerializeFormat & handler); - template void serialize(Handler &h, const int version) + template void serialize(Handler & h, const int version) { h & static_cast(*this); + h & static_cast(*this); + h & static_cast(*this); h & image; h & large; h & advMapDef; h & iconIndex; h & price; h & possibleSlots; - h & constituents; - h & constituentOf; h & aClass; h & id; h & modScope; @@ -117,20 +158,6 @@ public: friend class CArtHandler; }; -class DLL_LINKAGE CGrowingArtifact : public CArtifact //for example commander artifacts getting bonuses after battle -{ -public: - std::vector > bonusesPerLevel; //bonus given each n levels - std::vector > thresholdBonuses; //after certain level they will be added once - - template void serialize(Handler &h, const int version) - { - h & static_cast(*this); - h & bonusesPerLevel; - h & thresholdBonuses; - } -}; - class DLL_LINKAGE CArtHandler : public CHandlerBase { public: @@ -186,7 +213,6 @@ private: void loadClass(CArtifact * art, const JsonNode & node) const; void loadType(CArtifact * art, const JsonNode & node) const; void loadComponents(CArtifact * art, const JsonNode & node); - void loadGrowingArt(CGrowingArtifact * art, const JsonNode & node) const; void erasePickedArt(const ArtifactID & id); }; diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index c8dcede34..92bcf590d 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -58,15 +58,16 @@ void CGrowingArtifactInstance::growingUp() { auto artInst = static_cast(this); - if(auto growingArtType = dynamic_cast(static_cast(artInst->artType))) + if(artInst->artType->isGrowing()) { + auto bonus = std::make_shared(); bonus->type = BonusType::LEVEL_COUNTER; bonus->val = 1; bonus->duration = BonusDuration::COMMANDER_KILLED; artInst->accumulateBonus(bonus); - for(const auto & bonus : growingArtType->bonusesPerLevel) + for(const auto & bonus : artInst->artType->bonusesPerLevel) { // Every n levels if(artInst->valOfBonuses(BonusType::LEVEL_COUNTER) % bonus.first == 0) @@ -74,7 +75,7 @@ void CGrowingArtifactInstance::growingUp() artInst->accumulateBonus(std::make_shared(bonus.second)); } } - for(const auto & bonus : growingArtType->thresholdBonuses) + for(const auto & bonus : artInst->artType->thresholdBonuses) { // At n level if(artInst->valOfBonuses(BonusType::LEVEL_COUNTER) == bonus.first) @@ -117,7 +118,7 @@ std::string CArtifactInstance::nodeName() const std::string CArtifactInstance::getDescription() const { std::string text = artType->getDescriptionTranslated(); - if(artType->getId() == ArtifactID::SPELL_SCROLL) + if(artType->isScroll()) ArtifactUtils::insertScrrollSpellName(text, getScrollSpellID()); return text; } @@ -132,9 +133,9 @@ bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestR return artType->canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved); } -bool CArtifactInstance::canBeDisassembled() const +bool CArtifactInstance::isCombined() const { - return artType->canBeDisassembled(); + return artType->isCombined(); } void CArtifactInstance::putAt(const ArtifactLocation & al) diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index aad5bf1d5..aab15d4b2 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -37,6 +37,11 @@ public: void addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & slot); // Checks if supposed part inst is part of this combined art inst bool isPart(const CArtifactInstance * supposedPart) const; + + template void serialize(Handler & h, const int version) + { + h & partsInfo; + } }; class DLL_LINKAGE CScrollArtifactInstance @@ -72,7 +77,7 @@ public: ArtifactID getTypeId() const; bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const; - bool canBeDisassembled() const; + bool isCombined() const; void putAt(const ArtifactLocation & al); void removeFrom(const ArtifactLocation & al); void move(const ArtifactLocation & src, const ArtifactLocation & dst); @@ -81,9 +86,9 @@ public: template void serialize(Handler & h, const int version) { h & static_cast(*this); + h & static_cast(*this); h & artType; h & id; - h & partsInfo; BONUS_TREE_DESERIALIZATION_FIX } }; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 8324cab8e..1aa32afda 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1528,7 +1528,7 @@ void NewArtifact::applyGs(CGameState *gs) assert(art->artType); art->setType(art->artType); - if(art->canBeDisassembled()) + if(art->isCombined()) { assert(art->artType->constituents); for(const auto & part : *art->artType->constituents) @@ -1827,7 +1827,7 @@ void EraseArtifact::applyGs(CGameState *gs) for(auto& p : aset->artifactsWorn) { auto art = p.second.artifact; - if(art->canBeDisassembled() && art->isPart(slot->artifact)) + if(art->isCombined() && art->isPart(slot->artifact)) { dis.al.slot = aset->getArtPos(art); #ifndef NDEBUG @@ -2226,6 +2226,10 @@ void BattleResultAccepted::applyGs(CGameState * gs) const art.second.artifact->growingUp(); } } + for(auto & art : h->artifactsWorn) + { + art.second.artifact->growingUp(); + } } } diff --git a/lib/registerTypes/RegisterTypes.h b/lib/registerTypes/RegisterTypes.h index 405c9bbab..c23a60074 100644 --- a/lib/registerTypes/RegisterTypes.h +++ b/lib/registerTypes/RegisterTypes.h @@ -206,7 +206,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/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index b1de0801e..57e44b768 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -118,7 +118,7 @@ void CMapGenerator::initQuestArtsRemaining() for (auto art : VLC->arth->objects) { //Don't use parts of combined artifacts - if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->getId()) && art->constituentOf.empty()) + if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->getId()) && art->partOf.empty()) questArtifacts.push_back(art->getId()); } } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 1093c2e65..f8ad8a809 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -4102,7 +4102,7 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition } else { - if(!destArtifact->canBeDisassembled()) + if(!destArtifact->isCombined()) COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble is not a combined artifact!"); if(ArtifactUtils::isSlotBackpack(artifactSlot) From 670999d40e59408407fb1586d902ff4e221b6ed8 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Fri, 30 Jun 2023 18:59:45 +0300 Subject: [PATCH 06/10] BattleResultAccepted fixed --- lib/NetPacks.h | 34 +++++++++++++++++++----------- lib/NetPacksLib.cpp | 46 +++++++++++++++++++---------------------- server/CGameHandler.cpp | 13 ++++++------ 3 files changed, 50 insertions(+), 43 deletions(-) diff --git a/lib/NetPacks.h b/lib/NetPacks.h index fc81cb5d7..e3a6f25c5 100644 --- a/lib/NetPacks.h +++ b/lib/NetPacks.h @@ -1491,20 +1491,30 @@ struct DLL_LINKAGE BattleSetActiveStack : public CPackForClient struct DLL_LINKAGE BattleResultAccepted : public CPackForClient { void applyGs(CGameState * gs) const; - - CGHeroInstance * hero1 = nullptr; - CGHeroInstance * hero2 = nullptr; - CArmedInstance * army1 = nullptr; - CArmedInstance * army2 = nullptr; - TExpType exp[2]; - template void serialize(Handler &h, const int version) + struct HeroBattleResults { - h & hero1; - h & hero2; - h & army1; - h & army2; - h & exp; + HeroBattleResults() + : hero(nullptr), army(nullptr), exp(0) {} + + CGHeroInstance * hero; + CArmedInstance * army; + TExpType exp; + + template void serialize(Handler & h, const int version) + { + h & hero; + h & army; + h & exp; + } + }; + std::array heroResult; + ui8 winnerSide; + + template void serialize(Handler & h, const int version) + { + h & heroResult; + h & winnerSide; } }; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 1aa32afda..bd9709126 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -2214,36 +2214,32 @@ void BattleUpdateGateState::applyGs(CGameState * gs) const void BattleResultAccepted::applyGs(CGameState * gs) const { - for(auto * h : {hero1, hero2}) + // Remove any "until next battle" bonuses + for(auto & res : heroResult) { - if(h) - { - h->removeBonusesRecursive(Bonus::OneBattle); //remove any "until next battle" bonuses - if (h->commander && h->commander->alive) - { - for (auto art : h->commander->artifactsWorn) //increment bonuses for commander artifacts - { - art.second.artifact->growingUp(); - } - } - for(auto & art : h->artifactsWorn) - { - art.second.artifact->growingUp(); - } - } + if(res.hero) + res.hero->removeBonusesRecursive(Bonus::OneBattle); } + // Grow up growing artifacts + if(const auto hero = heroResult[winnerSide].hero) + { + if(hero->commander && hero->commander->alive) + { + for(auto & art : hero->commander->artifactsWorn) + art.second.artifact->growingUp(); + } + for(auto & art : hero->artifactsWorn) + { + art.second.artifact->growingUp(); + } + } if(VLC->settings()->getBoolean(EGameSettings::MODULE_STACK_EXPERIENCE)) { - for(int i = 0; i < 2; i++) - { - if(exp[i]) - { - if(auto * army = (i == 0 ? army1 : army2)) - army->giveStackExp(exp[i]); - } - } - + if(heroResult[0].army) + heroResult[0].army->giveStackExp(heroResult[0].exp); + if(heroResult[1].army) + heroResult[1].army->giveStackExp(heroResult[1].exp); CBonusSystemNode::treeHasChanged(); } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index f8ad8a809..a32a39f40 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -807,12 +807,13 @@ void CGameHandler::endBattleConfirm(const BattleInfo * battleInfo) changePrimSkill(finishingBattle->winnerHero, PrimarySkill::EXPERIENCE, battleResult.data->exp[finishingBattle->winnerSide]); BattleResultAccepted raccepted; - raccepted.army1 = const_cast(bEndArmy1); - raccepted.army2 = const_cast(bEndArmy2); - raccepted.hero1 = const_cast(battleInfo->sides.at(0).hero); - raccepted.hero2 = const_cast(battleInfo->sides.at(1).hero); - raccepted.exp[0] = battleResult.data->exp[0]; - raccepted.exp[1] = battleResult.data->exp[1]; + raccepted.heroResult[0].army = const_cast(bEndArmy1); + raccepted.heroResult[1].army = const_cast(bEndArmy2); + raccepted.heroResult[0].hero = const_cast(battleInfo->sides.at(0).hero); + raccepted.heroResult[1].hero = const_cast(battleInfo->sides.at(1).hero); + raccepted.heroResult[0].exp = battleResult.data->exp[0]; + raccepted.heroResult[1].exp = battleResult.data->exp[1]; + raccepted.winnerSide = finishingBattle->winnerSide; sendAndApply(&raccepted); queries.popIfTop(battleQuery); From aa90433418562ae9fbc561527f0718537d14c7a5 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Fri, 30 Jun 2023 19:14:53 +0300 Subject: [PATCH 07/10] bump serialization version --- lib/serializer/CSerializer.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/serializer/CSerializer.h b/lib/serializer/CSerializer.h index 52c556a6a..62e76c9a2 100644 --- a/lib/serializer/CSerializer.h +++ b/lib/serializer/CSerializer.h @@ -14,8 +14,8 @@ VCMI_LIB_NAMESPACE_BEGIN -const ui32 SERIALIZATION_VERSION = 823; -const ui32 MINIMAL_SERIALIZATION_VERSION = 823; +const ui32 SERIALIZATION_VERSION = 824; +const ui32 MINIMAL_SERIALIZATION_VERSION = 824; const std::string SAVEGAME_MAGIC = "VCMISVG"; class CHero; From 11a109f3afbcbd43c90606a7967da0ffd717fe91 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Fri, 30 Jun 2023 21:02:57 +0300 Subject: [PATCH 08/10] fix build --- lib/ArtifactUtils.cpp | 2 +- lib/ArtifactUtils.h | 2 +- lib/CArtifactInstance.cpp | 4 ++++ 3 files changed, 6 insertions(+), 2 deletions(-) diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index 32d1b2cf0..8e38bdb34 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -219,7 +219,7 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const return art; } -DLL_LINKAGE void ArtifactUtils::insertScrrollSpellName(std::string & description, SpellID & sid) +DLL_LINKAGE void ArtifactUtils::insertScrrollSpellName(std::string & description, const SpellID & sid) { // We expect scroll description to be like this: This scroll contains the [spell name] spell which is added // into spell book for as long as hero carries the scroll. So we want to replace text in [...] with a spell name. diff --git a/lib/ArtifactUtils.h b/lib/ArtifactUtils.h index b4feadbe8..c7b893dee 100644 --- a/lib/ArtifactUtils.h +++ b/lib/ArtifactUtils.h @@ -41,7 +41,7 @@ namespace ArtifactUtils DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(CArtifact * art); DLL_LINKAGE CArtifactInstance * createNewArtifactInstance(const ArtifactID & aid); DLL_LINKAGE CArtifactInstance * createArtifact(CMap * map, const ArtifactID & aid, int spellID = -1); - DLL_LINKAGE void insertScrrollSpellName(std::string & description, SpellID & sid); + DLL_LINKAGE void insertScrrollSpellName(std::string & description, const SpellID & sid); } VCMI_LIB_NAMESPACE_END diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 92bcf590d..265899ef0 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -15,6 +15,8 @@ #include "CArtHandler.h" #include "NetPacksBase.h" +VCMI_LIB_NAMESPACE_BEGIN + void CCombinedArtifactInstance::addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & slot) { auto artInst = static_cast(this); @@ -165,3 +167,5 @@ void CArtifactInstance::deserializationFix() for(PartInfo & part : partsInfo) attachTo(*part.art); } + +VCMI_LIB_NAMESPACE_END From fd9c7352a0701d5b91e63962ee400c5d0e5422a3 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 3 Jul 2023 19:15:40 +0300 Subject: [PATCH 09/10] suggested changes --- client/widgets/CArtifactHolder.cpp | 6 +-- client/widgets/CArtifactsOfHeroAltar.cpp | 2 +- client/widgets/CArtifactsOfHeroBase.cpp | 4 +- lib/ArtifactUtils.cpp | 10 ++--- lib/CArtHandler.cpp | 57 ++++++++++++++++++++---- lib/CArtHandler.h | 19 +++++--- lib/CArtifactInstance.cpp | 16 +++++-- lib/CArtifactInstance.h | 7 ++- lib/NetPacksLib.cpp | 12 ++--- lib/mapObjects/CQuest.cpp | 4 +- lib/mapping/MapFormatH3M.cpp | 2 +- lib/rmg/CMapGenerator.cpp | 2 +- server/CGameHandler.cpp | 4 +- 13 files changed, 103 insertions(+), 42 deletions(-) diff --git a/client/widgets/CArtifactHolder.cpp b/client/widgets/CArtifactHolder.cpp index f2aaf7ee1..34cb7117a 100644 --- a/client/widgets/CArtifactHolder.cpp +++ b/client/widgets/CArtifactHolder.cpp @@ -236,11 +236,11 @@ void CHeroArtPlace::addCombinedArtInfo(std::map & arts) text += "{" + combinedArt.first->getNameTranslated() + "}"; if(arts.size() == 1) { - for(const auto part : *combinedArt.first->constituents) + for(const auto part : combinedArt.first->getConstituents()) artList += "\n" + part->getNameTranslated(); } text += " (" + boost::str(boost::format("%d") % combinedArt.second) + " / " + - boost::str(boost::format("%d") % combinedArt.first->constituents->size()) + ")" + artList; + boost::str(boost::format("%d") % combinedArt.first->getConstituents().size()) + ")" + artList; } } @@ -292,7 +292,7 @@ bool ArtifactUtilsClient::askToDisassemble(const CGHeroInstance * hero, const Ar if(art->isCombined()) { - if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->constituents->size() - 1)) + if(ArtifactUtils::isSlotBackpack(slot) && !ArtifactUtils::isBackpackFreeSlots(hero, art->artType->getConstituents().size() - 1)) return false; LOCPLINT->showArtifactAssemblyDialog( diff --git a/client/widgets/CArtifactsOfHeroAltar.cpp b/client/widgets/CArtifactsOfHeroAltar.cpp index b12e3abdf..8a7bd01b6 100644 --- a/client/widgets/CArtifactsOfHeroAltar.cpp +++ b/client/widgets/CArtifactsOfHeroAltar.cpp @@ -98,7 +98,7 @@ void CArtifactsOfHeroAltar::deleteFromVisible(const CArtifactInstance * artInst) } else { - for(const auto & part : artInst->partsInfo) + for(const auto & part : artInst->getPartsInfo()) { if(part.slot != ArtifactPosition::PRE_FIRST) getArtPlace(part.slot)->setArtifact(nullptr); diff --git a/client/widgets/CArtifactsOfHeroBase.cpp b/client/widgets/CArtifactsOfHeroBase.cpp index 9afe6a20e..8c9039770 100644 --- a/client/widgets/CArtifactsOfHeroBase.cpp +++ b/client/widgets/CArtifactsOfHeroBase.cpp @@ -261,10 +261,10 @@ void CArtifactsOfHeroBase::setSlotData(ArtPlacePtr artPlace, const ArtifactPosit { // If the artifact is part of at least one combined artifact, add additional information std::map arts; - for(const auto combinedArt : slotInfo->artifact->artType->partOf) + for(const auto combinedArt : slotInfo->artifact->artType->getPartOf()) { arts.insert(std::pair(combinedArt, 0)); - for(const auto part : *combinedArt->constituents) + for(const auto part : combinedArt->getConstituents()) if(artSet.hasArt(part->getId(), true)) arts.at(combinedArt)++; } diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index 8e38bdb34..f1ef234d1 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -123,12 +123,12 @@ DLL_LINKAGE std::vector ArtifactUtils::assemblyPossibilities( if(art->isCombined()) return arts; - for(const auto artifact : art->partOf) + for(const auto artifact : art->getPartOf()) { assert(artifact->constituents); bool possible = true; - for(const auto constituent : *artifact->constituents) //check if all constituents are available + for(const auto constituent : artifact->getConstituents()) //check if all constituents are available { if(equipped) { @@ -172,8 +172,8 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createNewArtifactInstance(CArtifa if(art->isCombined()) { assert(art->constituents); - for(const auto & part : *art->constituents) - artInst->addArtInstAsPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST); + for(const auto & part : art->getConstituents()) + artInst->addPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST); } if(art->isGrowing()) { @@ -211,7 +211,7 @@ DLL_LINKAGE CArtifactInstance * ArtifactUtils::createArtifact(CMap * map, const map->addNewArtifactInstance(art); if(art->artType && art->isCombined()) { - for(auto & part : art->partsInfo) + for(auto & part : art->getPartsInfo()) { map->addNewArtifactInstance(part.art); } diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index b98b7453e..5a2c769b9 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -48,7 +48,27 @@ VCMI_LIB_NAMESPACE_BEGIN bool CCombinedArtifact::isCombined() const { - return !(constituents == nullptr); + return !(constituents.empty()); +} + +std::vector & CCombinedArtifact::getConstituents() +{ + return constituents; +} + +const std::vector & CCombinedArtifact::getConstituents() const +{ + return constituents; +} + +std::vector & CCombinedArtifact::getPartOf() +{ + return partOf; +} + +const std::vector & CCombinedArtifact::getPartOf() const +{ + return partOf; } bool CScrollArtifact::isScroll() const @@ -61,6 +81,26 @@ bool CGrowingArtifact::isGrowing() const return !bonusesPerLevel.empty() || !thresholdBonuses.empty(); } +std::vector > & CGrowingArtifact::getBonusesPerLevel() +{ + return bonusesPerLevel; +} + +const std::vector > & CGrowingArtifact::getBonusesPerLevel() const +{ + return bonusesPerLevel; +} + +std::vector > & CGrowingArtifact::getThresholdBonuses() +{ + return thresholdBonuses; +} + +const std::vector > & CGrowingArtifact::getThresholdBonuses() const +{ + return thresholdBonuses; +} + int32_t CArtifact::getIndex() const { return id.toEnum(); @@ -180,7 +220,7 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b if(assumeDestRemoved) fittingSet.removeArtifact(slot); assert(constituents); - for(const auto art : *constituents) + for(const auto art : constituents) { auto possibleSlot = ArtifactUtils::getArtAnyPosition(&fittingSet, art->getId()); if(ArtifactUtils::isSlotEquipment(possibleSlot)) @@ -557,14 +597,13 @@ void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node) { if (!node["components"].isNull()) { - art->constituents = std::make_unique>(); for(const auto & component : node["components"].Vector()) { VLC->modh->identifiers.requestIdentifier("artifact", component, [=](si32 id) { // when this code is called both combinational art as well as component are loaded // so it is safe to access any of them - art->constituents->push_back(objects[id]); + art->constituents.push_back(objects[id]); objects[id]->partOf.push_back(art); }); } @@ -655,7 +694,7 @@ bool CArtHandler::legalArtifact(const ArtifactID & id) auto art = objects[id]; //assert ( (!art->constituents) || art->constituents->size() ); //artifacts is not combined or has some components - if(art->constituents) + if(art->isCombined()) return false; //no combo artifacts spawning if(art->aClass < CArtifact::ART_TREASURE || art->aClass > CArtifact::ART_RELIC) @@ -894,7 +933,7 @@ void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art) if(art->artType->isCombined() && ArtifactUtils::isSlotEquipment(slot)) { const CArtifactInstance * mainPart = nullptr; - for(const auto & part : art->partsInfo) + for(const auto & part : art->getPartsInfo()) if(vstd::contains(part.art->artType->possibleSlots.at(bearerType()), slot) && (part.slot == ArtifactPosition::PRE_FIRST)) { @@ -902,7 +941,7 @@ void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art) break; } - for(auto & part : art->partsInfo) + for(auto & part : art->getPartsInfo()) { if(part.art != mainPart) { @@ -923,7 +962,7 @@ void CArtifactSet::removeArtifact(ArtifactPosition slot) { if(art->isCombined()) { - for(auto & part : art->partsInfo) + for(auto & part : art->getPartsInfo()) { if(getArt(part.slot, false)) eraseArtSlot(part.slot); @@ -940,7 +979,7 @@ std::pair CArtifactSet::se auto art = slot.artifact; if(art->isCombined()) { - for(auto& ci : art->partsInfo) + for(auto & ci : art->getPartsInfo()) { if(ci.art->getTypeId() == aid) { diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index 8254e9f6e..dafb8c5c6 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -46,11 +46,15 @@ class DLL_LINKAGE CCombinedArtifact { protected: CCombinedArtifact() = default; -public: - std::unique_ptr> constituents; // Artifacts IDs a combined artifact consists of, or nullptr. - std::vector partOf; // Reverse map of constituents - combined arts that include this art + std::vector constituents; // Artifacts IDs a combined artifact consists of, or nullptr. + std::vector partOf; // Reverse map of constituents - combined arts that include this art +public: bool isCombined() const; + std::vector & getConstituents(); + const std::vector & getConstituents() const; + std::vector & getPartOf(); + const std::vector & getPartOf() const; template void serialize(Handler & h, const int version) { @@ -71,12 +75,17 @@ class DLL_LINKAGE CGrowingArtifact { protected: CGrowingArtifact() = default; -public: + std::vector > bonusesPerLevel; // Bonus given each n levels std::vector > thresholdBonuses; // After certain level they will be added once - +public: bool isGrowing() const; + std::vector > & getBonusesPerLevel(); + const std::vector > & getBonusesPerLevel() const; + std::vector > & getThresholdBonuses(); + const std::vector > & getThresholdBonuses() const; + template void serialize(Handler & h, const int version) { h & bonusesPerLevel; diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 265899ef0..39b135754 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -17,7 +17,7 @@ VCMI_LIB_NAMESPACE_BEGIN -void CCombinedArtifactInstance::addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & slot) +void CCombinedArtifactInstance::addPart(CArtifactInstance * art, const ArtifactPosition & slot) { auto artInst = static_cast(this); assert(vstd::contains_if(*artInst->artType->constituents, @@ -44,6 +44,16 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c return false; } +std::vector & CCombinedArtifactInstance::getPartsInfo() +{ + return partsInfo; +} + +const std::vector & CCombinedArtifactInstance::getPartsInfo() const +{ + return partsInfo; +} + SpellID CScrollArtifactInstance::getScrollSpellID() const { auto artInst = static_cast(this); @@ -69,7 +79,7 @@ void CGrowingArtifactInstance::growingUp() bonus->duration = BonusDuration::COMMANDER_KILLED; artInst->accumulateBonus(bonus); - for(const auto & bonus : artInst->artType->bonusesPerLevel) + for(const auto & bonus : artInst->artType->getBonusesPerLevel()) { // Every n levels if(artInst->valOfBonuses(BonusType::LEVEL_COUNTER) % bonus.first == 0) @@ -77,7 +87,7 @@ void CGrowingArtifactInstance::growingUp() artInst->accumulateBonus(std::make_shared(bonus.second)); } } - for(const auto & bonus : artInst->artType->thresholdBonuses) + for(const auto & bonus : artInst->artType->getThresholdBonuses()) { // At n level if(artInst->valOfBonuses(BonusType::LEVEL_COUNTER) == bonus.first) diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index aab15d4b2..7ddf8194e 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -33,15 +33,18 @@ public: PartInfo(CArtifactInstance * art = nullptr, const ArtifactPosition & slot = ArtifactPosition::PRE_FIRST) : art(art), slot(slot) {}; }; - std::vector partsInfo; - void addArtInstAsPart(CArtifactInstance * art, const ArtifactPosition & slot); + void addPart(CArtifactInstance * art, const ArtifactPosition & slot); // Checks if supposed part inst is part of this combined art inst bool isPart(const CArtifactInstance * supposedPart) const; + std::vector & getPartsInfo(); + const std::vector & getPartsInfo() const; template void serialize(Handler & h, const int version) { h & partsInfo; } +protected: + std::vector partsInfo; }; class DLL_LINKAGE CScrollArtifactInstance diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index bd9709126..6e03c38af 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1530,9 +1530,9 @@ void NewArtifact::applyGs(CGameState *gs) art->setType(art->artType); if(art->isCombined()) { - assert(art->artType->constituents); - for(const auto & part : *art->artType->constituents) - art->addArtInstAsPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST); + assert(art->artType->getConstituents()); + for(const auto & part : art->artType->getConstituents()) + art->addPart(ArtifactUtils::createNewArtifactInstance(part), ArtifactPosition::PRE_FIRST); } gs->map->addNewArtifactInstance(art); } @@ -1938,7 +1938,7 @@ void AssembledArtifact::applyGs(CGameState *gs) auto * combinedArt = new CArtifactInstance(builtArt); gs->map->addNewArtifactInstance(combinedArt); // Retrieve all constituents - for(const CArtifact * constituent : *builtArt->constituents) + for(const CArtifact * constituent : builtArt->getConstituents()) { ArtifactPosition pos = combineEquipped ? artSet->getArtPos(constituent->getId(), true, false) : artSet->getArtBackpackPos(constituent->getId()); @@ -1960,7 +1960,7 @@ void AssembledArtifact::applyGs(CGameState *gs) al.slot = std::min(al.slot, pos); pos = ArtifactPosition::PRE_FIRST; } - combinedArt->addArtInstAsPart(constituentInstance, pos); + combinedArt->addPart(constituentInstance, pos); } //put new combined artifacts @@ -1972,7 +1972,7 @@ void DisassembledArtifact::applyGs(CGameState *gs) auto * disassembled = al.getArt(); assert(disassembled); - auto parts = disassembled->partsInfo; + auto parts = disassembled->getPartsInfo(); disassembled->removeFrom(al); for(auto & part : parts) { diff --git a/lib/mapObjects/CQuest.cpp b/lib/mapObjects/CQuest.cpp index 01812d0d9..2018ca8dc 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)->partsInfo.size() - 2; + reqSlots += h->getAssemblyByConstituent(elem.first)->getPartsInfo().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->partsInfo; + auto parts = assembly->getPartsInfo(); // Remove the assembly cb->removeArtifact(ArtifactLocation(h, h->getArtPos(assembly))); diff --git a/lib/mapping/MapFormatH3M.cpp b/lib/mapping/MapFormatH3M.cpp index 665e38339..4b4f69af7 100644 --- a/lib/mapping/MapFormatH3M.cpp +++ b/lib/mapping/MapFormatH3M.cpp @@ -746,7 +746,7 @@ void CMapLoaderH3M::readAllowedArtifacts() if(!features.levelSOD) { for(CArtifact * artifact : VLC->arth->objects) - if(artifact->constituents) + if(artifact->isCombined()) map->allowedArtifact[artifact->getId()] = false; } diff --git a/lib/rmg/CMapGenerator.cpp b/lib/rmg/CMapGenerator.cpp index 57e44b768..be3fbd1d3 100644 --- a/lib/rmg/CMapGenerator.cpp +++ b/lib/rmg/CMapGenerator.cpp @@ -118,7 +118,7 @@ void CMapGenerator::initQuestArtsRemaining() for (auto art : VLC->arth->objects) { //Don't use parts of combined artifacts - if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->getId()) && art->partOf.empty()) + if (art->aClass == CArtifact::ART_TREASURE && VLC->arth->legalArtifact(art->getId()) && art->getPartOf().empty()) questArtifacts.push_back(art->getId()); } } diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index a32a39f40..364f488fd 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -4084,7 +4084,7 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition if(assemble) { CArtifact * combinedArt = VLC->arth->objects[assembleTo]; - if(!combinedArt->constituents) + if(!combinedArt->isCombined()) COMPLAIN_RET("assembleArtifacts: Artifact being attempted to assemble is not a combined artifacts!"); if (!vstd::contains(ArtifactUtils::assemblyPossibilities(hero, destArtifact->getTypeId(), ArtifactUtils::isSlotEquipment(artifactSlot)), combinedArt)) @@ -4107,7 +4107,7 @@ bool CGameHandler::assembleArtifacts (ObjectInstanceID heroID, ArtifactPosition COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble is not a combined artifact!"); if(ArtifactUtils::isSlotBackpack(artifactSlot) - && !ArtifactUtils::isBackpackFreeSlots(hero, destArtifact->artType->constituents->size() - 1)) + && !ArtifactUtils::isBackpackFreeSlots(hero, destArtifact->artType->getConstituents().size() - 1)) COMPLAIN_RET("assembleArtifacts: Artifact being attempted to disassemble but backpack is full!"); DisassembledArtifact da; From 9b5f6ec7cfda89ada69c9a4788e32d59f4380ac1 Mon Sep 17 00:00:00 2001 From: SoundSSGood <87084363+SoundSSGood@users.noreply.github.com> Date: Mon, 3 Jul 2023 23:11:56 +0300 Subject: [PATCH 10/10] CArtifact getters setters --- AI/Nullkiller/AIGateway.cpp | 4 ++-- AI/Nullkiller/AIUtility.cpp | 4 ++-- AI/VCAI/AIUtility.cpp | 4 ++-- AI/VCAI/VCAI.cpp | 4 ++-- client/windows/CCastleInterface.cpp | 2 +- client/windows/CCreatureWindow.cpp | 2 +- client/windows/CTradeWindow.cpp | 2 +- lib/ArtifactUtils.cpp | 2 +- lib/CArtHandler.cpp | 31 ++++++++++++++--------------- lib/CArtHandler.h | 22 ++++++++++---------- lib/CArtifactInstance.cpp | 11 ++++++++++ lib/CArtifactInstance.h | 5 ++++- lib/JsonRandom.cpp | 4 ++-- lib/NetPacksLib.cpp | 4 ++-- lib/battle/BattleInfo.cpp | 2 +- lib/mapObjects/CGHeroInstance.cpp | 4 ++-- lib/mapObjects/MiscObjects.cpp | 2 +- lib/mapping/CMap.cpp | 4 ++-- lib/serializer/CSerializer.cpp | 2 +- mapeditor/validator.cpp | 2 +- server/CGameHandler.cpp | 4 ++-- test/entity/CArtifactTest.cpp | 4 +--- 22 files changed, 68 insertions(+), 57 deletions(-) diff --git a/AI/Nullkiller/AIGateway.cpp b/AI/Nullkiller/AIGateway.cpp index 5566d3140..f18c77e5c 100644 --- a/AI/Nullkiller/AIGateway.cpp +++ b/AI/Nullkiller/AIGateway.cpp @@ -1000,7 +1000,7 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance //FIXME: why are the above possible to be null? bool emptySlotFound = false; - for(auto slot : artifact->artType->possibleSlots.at(target->bearerType())) + for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType())) { ArtifactLocation destLocation(target, slot); if(target->isPositionFree(slot) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move @@ -1013,7 +1013,7 @@ void AIGateway::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance } if(!emptySlotFound) //try to put that atifact in already occupied slot { - for(auto slot : artifact->artType->possibleSlots.at(target->bearerType())) + for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType())) { auto otherSlot = target->getSlot(slot); if(otherSlot && otherSlot->artifact) //we need to exchange artifact for better one diff --git a/AI/Nullkiller/AIUtility.cpp b/AI/Nullkiller/AIUtility.cpp index cdb260110..296c47780 100644 --- a/AI/Nullkiller/AIUtility.cpp +++ b/AI/Nullkiller/AIUtility.cpp @@ -306,10 +306,10 @@ bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2 auto art1 = a1->artType; auto art2 = a2->artType; - if(art1->price == art2->price) + if(art1->getPrice() == art2->getPrice()) return art1->valOfBonuses(BonusType::PRIMARY_SKILL) > art2->valOfBonuses(BonusType::PRIMARY_SKILL); else - return art1->price > art2->price; + return art1->getPrice() > art2->getPrice(); } bool isWeeklyRevisitable(const CGObjectInstance * obj) diff --git a/AI/VCAI/AIUtility.cpp b/AI/VCAI/AIUtility.cpp index a653dfcff..e73ddf191 100644 --- a/AI/VCAI/AIUtility.cpp +++ b/AI/VCAI/AIUtility.cpp @@ -256,8 +256,8 @@ bool compareArtifacts(const CArtifactInstance * a1, const CArtifactInstance * a2 auto art1 = a1->artType; auto art2 = a2->artType; - if(art1->price == art2->price) + if(art1->getPrice() == art2->getPrice()) return art1->valOfBonuses(BonusType::PRIMARY_SKILL) > art2->valOfBonuses(BonusType::PRIMARY_SKILL); else - return art1->price > art2->price; + return art1->getPrice() > art2->getPrice(); } diff --git a/AI/VCAI/VCAI.cpp b/AI/VCAI/VCAI.cpp index 0ec77b099..d027548c5 100644 --- a/AI/VCAI/VCAI.cpp +++ b/AI/VCAI/VCAI.cpp @@ -1187,7 +1187,7 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot //FIXME: why are the above possible to be null? bool emptySlotFound = false; - for(auto slot : artifact->artType->possibleSlots.at(target->bearerType())) + for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType())) { ArtifactLocation destLocation(target, slot); if(target->isPositionFree(slot) && artifact->canBePutAt(destLocation, true)) //combined artifacts are not always allowed to move @@ -1200,7 +1200,7 @@ void VCAI::pickBestArtifacts(const CGHeroInstance * h, const CGHeroInstance * ot } if(!emptySlotFound) //try to put that atifact in already occupied slot { - for(auto slot : artifact->artType->possibleSlots.at(target->bearerType())) + for(auto slot : artifact->artType->getPossibleSlots().at(target->bearerType())) { auto otherSlot = target->getSlot(slot); if(otherSlot && otherSlot->artifact) //we need to exchange artifact for better one diff --git a/client/windows/CCastleInterface.cpp b/client/windows/CCastleInterface.cpp index 91c6333d7..bcdc63153 100644 --- a/client/windows/CCastleInterface.cpp +++ b/client/windows/CCastleInterface.cpp @@ -800,7 +800,7 @@ void CCastleBuildings::enterBlacksmith(ArtifactID artifactID) bool possible = LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) >= price; if(possible) { - for(auto slot : art->possibleSlots.at(ArtBearer::HERO)) + for(auto slot : art->getPossibleSlots().at(ArtBearer::HERO)) { if(hero->getArt(slot) == nullptr) { diff --git a/client/windows/CCreatureWindow.cpp b/client/windows/CCreatureWindow.cpp index 214e7ec21..21d958c08 100644 --- a/client/windows/CCreatureWindow.cpp +++ b/client/windows/CCreatureWindow.cpp @@ -588,7 +588,7 @@ CStackWindow::MainSection::MainSection(CStackWindow * owner, int yOffset, bool s auto art = parent->info->stackNode->getArt(ArtifactPosition::CREATURE_SLOT); if(art) { - parent->stackArtifactIcon = std::make_shared("ARTIFACT", art->artType->iconIndex, 0, pos.x, pos.y); + parent->stackArtifactIcon = std::make_shared("ARTIFACT", art->artType->getIconIndex(), 0, pos.x, pos.y); parent->stackArtifactHelp = std::make_shared(Rect(pos, Point(44, 44)), CComponent::artifact); parent->stackArtifactHelp->type = art->artType->getId(); diff --git a/client/windows/CTradeWindow.cpp b/client/windows/CTradeWindow.cpp index c7e3f4ced..bc96ce464 100644 --- a/client/windows/CTradeWindow.cpp +++ b/client/windows/CTradeWindow.cpp @@ -803,7 +803,7 @@ void CMarketplaceWindow::makeDeal() leftIdToSend = hLeft->serial; break; case EMarketMode::ARTIFACT_RESOURCE: - leftIdToSend = hLeft->getArtInstance()->id.getNum(); + leftIdToSend = hLeft->getArtInstance()->getId().getNum(); break; case EMarketMode::RESOURCE_ARTIFACT: if(!ArtifactID(hRight->id).toArtifact()->canBePutAt(hero)) diff --git a/lib/ArtifactUtils.cpp b/lib/ArtifactUtils.cpp index f1ef234d1..c5ecf63f5 100644 --- a/lib/ArtifactUtils.cpp +++ b/lib/ArtifactUtils.cpp @@ -22,7 +22,7 @@ VCMI_LIB_NAMESPACE_BEGIN DLL_LINKAGE ArtifactPosition ArtifactUtils::getArtAnyPosition(const CArtifactSet * target, const ArtifactID & aid) { const auto * art = aid.toArtifact(); - for(const auto & slot : art->possibleSlots.at(target->bearerType())) + for(const auto & slot : art->getPossibleSlots().at(target->bearerType())) { if(art->canBePutAt(target, slot)) return slot; diff --git a/lib/CArtHandler.cpp b/lib/CArtHandler.cpp index 5a2c769b9..cf1c15aa5 100644 --- a/lib/CArtHandler.cpp +++ b/lib/CArtHandler.cpp @@ -51,21 +51,11 @@ bool CCombinedArtifact::isCombined() const return !(constituents.empty()); } -std::vector & CCombinedArtifact::getConstituents() -{ - return constituents; -} - const std::vector & CCombinedArtifact::getConstituents() const { return constituents; } -std::vector & CCombinedArtifact::getPartOf() -{ - return partOf; -} - const std::vector & CCombinedArtifact::getPartOf() const { return partOf; @@ -263,6 +253,8 @@ bool CArtifact::canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot, b } CArtifact::CArtifact() + : iconIndex(ArtifactID::NONE), + price(0) { setNodeType(ARTIFACT); possibleSlots[ArtBearer::HERO]; //we want to generate map entry even if it will be empty @@ -307,14 +299,21 @@ void CArtifact::addNewBonus(const std::shared_ptr& b) CBonusSystemNode::addNewBonus(b); } +const std::map> & CArtifact::getPossibleSlots() const +{ + return possibleSlots; +} + void CArtifact::updateFrom(const JsonNode& data) { //TODO:CArtifact::updateFrom } -void CArtifact::serializeJson(JsonSerializeFormat & handler) +void CArtifact::setImage(int32_t iconIndex, std::string image, std::string large) { - + this->iconIndex = iconIndex; + this->image = image; + this->large = large; } CArtHandler::~CArtHandler() = default; @@ -876,11 +875,11 @@ ArtifactPosition CArtifactSet::getArtPos(const CArtifactInstance *art) const const CArtifactInstance * CArtifactSet::getArtByInstanceId(const ArtifactInstanceID & artInstId) const { for(auto i : artifactsWorn) - if(i.second.artifact->id == artInstId) + if(i.second.artifact->getId() == artInstId) return i.second.artifact; for(auto i : artifactsInBackpack) - if(i.artifact->id == artInstId) + if(i.artifact->getId() == artInstId) return i.artifact; return nullptr; @@ -890,7 +889,7 @@ const ArtifactPosition CArtifactSet::getSlotByInstance(const CArtifactInstance * { if(artInst) { - for(auto & slot : artInst->artType->possibleSlots.at(bearerType())) + for(const auto & slot : artInst->artType->getPossibleSlots().at(bearerType())) if(getArt(slot) == artInst) return slot; @@ -934,7 +933,7 @@ void CArtifactSet::putArtifact(ArtifactPosition slot, CArtifactInstance * art) { const CArtifactInstance * mainPart = nullptr; for(const auto & part : art->getPartsInfo()) - if(vstd::contains(part.art->artType->possibleSlots.at(bearerType()), slot) + if(vstd::contains(part.art->artType->getPossibleSlots().at(bearerType()), slot) && (part.slot == ArtifactPosition::PRE_FIRST)) { mainPart = part.art; diff --git a/lib/CArtHandler.h b/lib/CArtHandler.h index dafb8c5c6..640de2c6c 100644 --- a/lib/CArtHandler.h +++ b/lib/CArtHandler.h @@ -51,9 +51,7 @@ protected: std::vector partOf; // Reverse map of constituents - combined arts that include this art public: bool isCombined() const; - std::vector & getConstituents(); const std::vector & getConstituents() const; - std::vector & getPartOf(); const std::vector & getPartOf() const; template void serialize(Handler & h, const int version) @@ -98,21 +96,21 @@ class DLL_LINKAGE CArtifact : public Artifact, public CBonusSystemNode, public CCombinedArtifact, public CScrollArtifact, public CGrowingArtifact { ArtifactID id; - + std::string image; + std::string large; // big image for custom artifacts, used in drag & drop + std::string advMapDef; // used for adventure map object std::string modScope; std::string identifier; + int32_t iconIndex; + uint32_t price; + CreatureID warMachine; + // Bearer Type => ids of slots where artifact can be placed + std::map> possibleSlots; public: enum EartClass {ART_SPECIAL=1, ART_TREASURE=2, ART_MINOR=4, ART_MAJOR=8, ART_RELIC=16}; //artifact classes - std::string image; - std::string large; // big image for custom artifacts, used in drag & drop - std::string advMapDef; //used for adventure map object - si32 iconIndex = ArtifactID::NONE; - ui32 price = 0; - std::map > possibleSlots; //Bearer Type => ids of slots where artifact can be placed EartClass aClass = ART_SPECIAL; - CreatureID warMachine; int32_t getIndex() const override; int32_t getIconIndex() const override; @@ -137,11 +135,13 @@ public: int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other std::string nodeName() const override; void addNewBonus(const std::shared_ptr& b) override; + const std::map> & getPossibleSlots() const; virtual bool canBePutAt(const CArtifactSet * artSet, ArtifactPosition slot = ArtifactPosition::FIRST_AVAILABLE, bool assumeDestRemoved = false) const; void updateFrom(const JsonNode & data); - void serializeJson(JsonSerializeFormat & handler); + // Is used for testing purposes only + void setImage(int32_t iconIndex, std::string image, std::string large); template void serialize(Handler & h, const int version) { diff --git a/lib/CArtifactInstance.cpp b/lib/CArtifactInstance.cpp index 39b135754..679fa387b 100644 --- a/lib/CArtifactInstance.cpp +++ b/lib/CArtifactInstance.cpp @@ -46,6 +46,7 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c std::vector & CCombinedArtifactInstance::getPartsInfo() { + // TODO romove this func. encapsulation violation return partsInfo; } @@ -140,6 +141,16 @@ ArtifactID CArtifactInstance::getTypeId() const return artType->getId(); } +ArtifactInstanceID CArtifactInstance::getId() const +{ + return id; +} + +void CArtifactInstance::setId(ArtifactInstanceID id) +{ + this->id = id; +} + bool CArtifactInstance::canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved) const { return artType->canBePutAt(al.getHolderArtSet(), al.slot, assumeDestRemoved); diff --git a/lib/CArtifactInstance.h b/lib/CArtifactInstance.h index 7ddf8194e..079db214f 100644 --- a/lib/CArtifactInstance.h +++ b/lib/CArtifactInstance.h @@ -68,9 +68,10 @@ class DLL_LINKAGE CArtifactInstance { protected: void init(); + + ArtifactInstanceID id; public: ConstTransitivePtr artType; - ArtifactInstanceID id; CArtifactInstance(CArtifact * art); CArtifactInstance(); @@ -78,6 +79,8 @@ public: std::string nodeName() const override; std::string getDescription() const; ArtifactID getTypeId() const; + ArtifactInstanceID getId() const; + void setId(ArtifactInstanceID id); bool canBePutAt(const ArtifactLocation & al, bool assumeDestRemoved = false) const; bool isCombined() const; diff --git a/lib/JsonRandom.cpp b/lib/JsonRandom.cpp index 3be169f88..222d8aacf 100644 --- a/lib/JsonRandom.cpp +++ b/lib/JsonRandom.cpp @@ -206,7 +206,7 @@ namespace JsonRandom { CArtifact * art = VLC->arth->objects[artID]; - if(!vstd::iswithin(art->price, minValue, maxValue)) + if(!vstd::iswithin(art->getPrice(), minValue, maxValue)) return false; if(!allowedClasses.empty() && !allowedClasses.count(art->aClass)) @@ -217,7 +217,7 @@ namespace JsonRandom if(!allowedPositions.empty()) { - for(const auto & pos : art->possibleSlots[ArtBearer::HERO]) + for(const auto & pos : art->getPossibleSlots().at(ArtBearer::HERO)) { if(allowedPositions.count(pos)) return true; diff --git a/lib/NetPacksLib.cpp b/lib/NetPacksLib.cpp index 6e03c38af..95da6a4e6 100644 --- a/lib/NetPacksLib.cpp +++ b/lib/NetPacksLib.cpp @@ -1949,8 +1949,8 @@ void AssembledArtifact::applyGs(CGameState *gs) constituentInstance->removeFrom(ArtifactLocation(al.artHolder, pos)); if(combineEquipped) { - if(!vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], al.slot) - && vstd::contains(combinedArt->artType->possibleSlots[artSet->bearerType()], pos)) + if(!vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), al.slot) + && vstd::contains(combinedArt->artType->getPossibleSlots().at(artSet->bearerType()), pos)) al.slot = pos; if(al.slot == pos) pos = ArtifactPosition::PRE_FIRST; diff --git a/lib/battle/BattleInfo.cpp b/lib/battle/BattleInfo.cpp index dd80dc0e8..861e45c52 100644 --- a/lib/battle/BattleInfo.cpp +++ b/lib/battle/BattleInfo.cpp @@ -378,7 +378,7 @@ BattleInfo * BattleInfo::setupBattle(const int3 & tile, TerrainId terrain, const if(nullptr != warMachineArt) { - CreatureID cre = warMachineArt->artType->warMachine; + CreatureID cre = warMachineArt->artType->getWarMachine(); if(cre != CreatureID::NONE) curB->generateNewStack(curB->nextUnitId(), CStackBasicDescriptor(cre, 1), side, SlotID::WAR_MACHINES_SLOT, hex); diff --git a/lib/mapObjects/CGHeroInstance.cpp b/lib/mapObjects/CGHeroInstance.cpp index dfbe598b3..0e4a384a9 100644 --- a/lib/mapObjects/CGHeroInstance.cpp +++ b/lib/mapObjects/CGHeroInstance.cpp @@ -406,10 +406,10 @@ void CGHeroInstance::initArmy(CRandomGenerator & rand, IArmyDescriptor * dst) ArtifactID aid = creature->warMachine; const CArtifact * art = aid.toArtifact(); - if(art != nullptr && !art->possibleSlots.at(ArtBearer::HERO).empty()) + if(art != nullptr && !art->getPossibleSlots().at(ArtBearer::HERO).empty()) { //TODO: should we try another possible slots? - ArtifactPosition slot = art->possibleSlots.at(ArtBearer::HERO).front(); + ArtifactPosition slot = art->getPossibleSlots().at(ArtBearer::HERO).front(); if(!getArt(slot)) putArtifact(slot, ArtifactUtils::createNewArtifactInstance(aid)); diff --git a/lib/mapObjects/MiscObjects.cpp b/lib/mapObjects/MiscObjects.cpp index 41639007c..c5e4fdbda 100644 --- a/lib/mapObjects/MiscObjects.cpp +++ b/lib/mapObjects/MiscObjects.cpp @@ -820,7 +820,7 @@ void CGArtifact::afterAddToMap(CMap * map) //Artifacts from map objects are never removed //FIXME: This should be revertible in map editor - if(ID == Obj::SPELL_SCROLL && storedArtifact && storedArtifact->id.getNum() < 0) + if(ID == Obj::SPELL_SCROLL && storedArtifact && storedArtifact->getId().getNum() < 0) map->addNewArtifactInstance(storedArtifact); } diff --git a/lib/mapping/CMap.cpp b/lib/mapping/CMap.cpp index 1533bdfbf..9f11fe561 100644 --- a/lib/mapping/CMap.cpp +++ b/lib/mapping/CMap.cpp @@ -466,7 +466,7 @@ void CMap::checkForObjectives() void CMap::addNewArtifactInstance(CArtifactInstance * art) { - art->id = ArtifactInstanceID(static_cast(artInstances.size())); + art->setId(static_cast(artInstances.size())); artInstances.emplace_back(art); } @@ -474,7 +474,7 @@ void CMap::eraseArtifactInstance(CArtifactInstance * art) { //TODO: handle for artifacts removed in map editor assert(artInstances[art->id.getNum()] == art); - artInstances[art->id.getNum()].dellNull(); + artInstances[art->getId().getNum()].dellNull(); } void CMap::addNewQuestInstance(CQuest* quest) diff --git a/lib/serializer/CSerializer.cpp b/lib/serializer/CSerializer.cpp index b8fc03770..1ce13bfe3 100644 --- a/lib/serializer/CSerializer.cpp +++ b/lib/serializer/CSerializer.cpp @@ -33,7 +33,7 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib) registerVectoredType(&lib->arth->objects, [](const CArtifact &art){ return art.getId(); }); registerVectoredType(&gs->map->artInstances, - [](const CArtifactInstance &artInst){ return artInst.id; }); + [](const CArtifactInstance &artInst){ return artInst.getId(); }); registerVectoredType(&gs->map->quests, [](const CQuest &q){ return q.qid; }); diff --git a/mapeditor/validator.cpp b/mapeditor/validator.cpp index 92950f0d4..a564c8204 100644 --- a/mapeditor/validator.cpp +++ b/mapeditor/validator.cpp @@ -140,7 +140,7 @@ std::list Validator::validate(const CMap * map) { if(ins->storedArtifact) { - if(!map->allowedSpell[ins->storedArtifact->id.getNum()]) + if(!map->allowedSpell[ins->storedArtifact->getId().getNum()]) issues.emplace_back(QString("Spell scroll %1 is prohibited by map settings").arg(ins->getObjectName().c_str()), false); } else diff --git a/server/CGameHandler.cpp b/server/CGameHandler.cpp index 364f488fd..ea42aea0a 100644 --- a/server/CGameHandler.cpp +++ b/server/CGameHandler.cpp @@ -4160,9 +4160,9 @@ bool CGameHandler::buyArtifact(ObjectInstanceID hid, ArtifactID aid) { const CArtifact * art = aid.toArtifact(); COMPLAIN_RET_FALSE_IF(nullptr == art, "Invalid artifact index to buy"); - COMPLAIN_RET_FALSE_IF(art->warMachine == CreatureID::NONE, "War machine artifact required"); + COMPLAIN_RET_FALSE_IF(art->getWarMachine() == CreatureID::NONE, "War machine artifact required"); COMPLAIN_RET_FALSE_IF(hero->hasArt(aid),"Hero already has this machine!"); - const int price = art->price; + const int price = art->getPrice(); COMPLAIN_RET_FALSE_IF(getPlayerState(hero->getOwner())->resources[EGameResID::GOLD] < price, "Not enough gold!"); if ((town->hasBuilt(BuildingID::BLACKSMITH) && town->town->warMachine == aid) diff --git a/test/entity/CArtifactTest.cpp b/test/entity/CArtifactTest.cpp index b4a6b8e23..c3517d89b 100644 --- a/test/entity/CArtifactTest.cpp +++ b/test/entity/CArtifactTest.cpp @@ -32,9 +32,7 @@ protected: TEST_F(CArtifactTest, RegistersIcons) { - subject->iconIndex = 4242; - subject->image = "Test1"; - subject->large = "Test2"; + subject-> setImage(4242, "Test1", "Test2"); auto cb = [this](auto && PH1, auto && PH2, auto && PH3, auto && PH4) {