瀏覽代碼

CArtifact refactoring

SoundSSGood 2 年之前
父節點
當前提交
060aecc61c

+ 1 - 1
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;

+ 2 - 2
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<const CArtifact*, int> 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)

+ 5 - 5
lib/ArtifactUtils.cpp

@@ -120,10 +120,10 @@ DLL_LINKAGE std::vector<const CArtifact*> ArtifactUtils::assemblyPossibilities(
 {
 	std::vector<const CArtifact*> 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<CGrowingArtifact*>(art))
+	if(art->isGrowing())
 	{
 		auto bonus = std::make_shared<Bonus>();
 		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)
 		{

+ 32 - 34
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<const CArtifact*>(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<ui16>(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<ui16>(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<ui16>(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<ui16>(b["level"].Float()), Bonus());
-		JsonUtils::parseBonus(b["bonus"], &art->thresholdBonuses.back().second);
-	}
-}
-
 ArtifactID CArtHandler::pickRandomArtifact(CRandomGenerator & rand, int flags, std::function<bool(ArtifactID)> accepts)
 {
 	auto getAllowedArts = [&](std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *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<const CArtifactInstance *, const CArtifactInstance *> CArtifactSet::se
 	for(const auto & slot : artifactsInBackpack)
 	{
 		auto art = slot.artifact;
-		if(art->canBeDisassembled())
+		if(art->isCombined())
 		{
 			for(auto& ci : art->partsInfo)
 			{

+ 48 - 22
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<std::vector<CArtifact*>> constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
+	std::vector<CArtifact*> partOf; // Reverse map of constituents - combined arts that include this art
+
+	bool isCombined() const;
+
+	template <typename Handler> 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 <std::pair<ui16, Bonus>> bonusesPerLevel; // Bonus given each n levels
+	std::vector <std::pair<ui16, Bonus>> thresholdBonuses; // After certain level they will be added once
+
+	bool isGrowing() const;
+
+	template <typename Handler> 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<ArtBearer::ArtBearer, std::vector<ArtifactPosition> > possibleSlots; //Bearer Type => ids of slots where artifact can be placed
-	std::unique_ptr<std::vector<CArtifact *> > constituents; // Artifacts IDs a combined artifact consists of, or nullptr.
-	std::vector<CArtifact *> 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<Bonus>& 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 <typename Handler> void serialize(Handler &h, const int version)
+	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & static_cast<CBonusSystemNode&>(*this);
+		h & static_cast<CCombinedArtifact&>(*this);
+		h & static_cast<CGrowingArtifact&>(*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 <std::pair <ui16, Bonus> > bonusesPerLevel; //bonus given each n levels
-	std::vector <std::pair <ui16, Bonus> > thresholdBonuses; //after certain level they will be added once
-
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & static_cast<CArtifact&>(*this);
-		h & bonusesPerLevel;
-		h & thresholdBonuses;
-	}
-};
-
 class DLL_LINKAGE CArtHandler : public CHandlerBase<ArtifactID, Artifact, CArtifact, ArtifactService>
 {
 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);
 };

+ 7 - 6
lib/CArtifactInstance.cpp

@@ -58,15 +58,16 @@ void CGrowingArtifactInstance::growingUp()
 {
 	auto artInst = static_cast<CArtifactInstance*>(this);
 	
-	if(auto growingArtType = dynamic_cast<const CGrowingArtifact*>(static_cast<const CArtifact*>(artInst->artType)))
+	if(artInst->artType->isGrowing())
 	{
+
 		auto bonus = std::make_shared<Bonus>();
 		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>(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)

+ 7 - 2
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 <typename Handler> 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 <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & static_cast<CBonusSystemNode&>(*this);
+		h & static_cast<CCombinedArtifactInstance&>(*this);
 		h & artType;
 		h & id;
-		h & partsInfo;
 		BONUS_TREE_DESERIALIZATION_FIX
 	}
 };

+ 6 - 2
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();
+			}
 		}
 	}
 

+ 0 - 1
lib/registerTypes/RegisterTypes.h

@@ -206,7 +206,6 @@ void registerTypesMapObjects2(Serializer &s)
 
 //	s.template registerType<CBonusSystemNode>();
 	s.template registerType<CBonusSystemNode, CArtifact>();
-	s.template registerType<CArtifact, CGrowingArtifact>();
 	s.template registerType<CBonusSystemNode, CCreature>();
 	s.template registerType<CBonusSystemNode, CStackInstance>();
 	s.template registerType<CStackInstance, CCommanderInstance>();

+ 1 - 1
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());
 	}
 }

+ 1 - 1
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)