浏览代码

Fix crash on loading map with heroes that have combined art equipped

Ivan Savenko 5 月之前
父节点
当前提交
69de14a42f

+ 14 - 11
lib/entities/artifact/CArtifactInstance.cpp

@@ -19,22 +19,22 @@
 
 VCMI_LIB_NAMESPACE_BEGIN
 
-CCombinedArtifactInstance::PartInfo::PartInfo(IGameCallback * cb)
-	:GameCallbackHolder(cb)
-{}
-
 CCombinedArtifactInstance::PartInfo::PartInfo(const CArtifactInstance * artifact, ArtifactPosition slot)
-	: GameCallbackHolder(artifact->cb)
-	, artifactID(artifact->getId())
+	: artifactID(artifact->getId())
+	, artifactPtr(artifact)
 	, slot(slot)
 {
 }
 
 const CArtifactInstance * CCombinedArtifactInstance::PartInfo::getArtifact() const
 {
-	if (artifactID.hasValue())
-		return cb->getArtInstance(artifactID);
-	return nullptr;
+	assert(artifactPtr != nullptr || !artifactID.hasValue());
+	return artifactPtr;
+}
+
+ArtifactInstanceID CCombinedArtifactInstance::PartInfo::getArtifactID() const
+{
+	return artifactID;
 }
 
 void CCombinedArtifactInstance::addPart(const CArtifactInstance * art, const ArtifactPosition & slot)
@@ -57,7 +57,7 @@ bool CCombinedArtifactInstance::isPart(const CArtifactInstance * supposedPart) c
 
 	for(const PartInfo & constituent : partsInfo)
 	{
-		if(constituent.artifactID == supposedPart->getId())
+		if(constituent.getArtifactID() == supposedPart->getId())
 			return true;
 	}
 
@@ -186,7 +186,10 @@ bool CArtifactInstance::isScroll() const
 void CArtifactInstance::attachToBonusSystem(CGameState & gs)
 {
 	for(PartInfo & part : partsInfo)
-		attachToSource(*gs.getArtInstance(part.artifactID));
+	{
+		part = PartInfo(gs.getArtInstance(part.getArtifactID()), part.slot);
+		attachToSource(*gs.getArtInstance(part.getArtifactID()));
+	}
 }
 
 void CArtifactInstance::saveCompatibilityFixArtifactID(std::shared_ptr<CArtifactInstance> self)

+ 10 - 4
lib/entities/artifact/CArtifactInstance.h

@@ -22,18 +22,24 @@ class DLL_LINKAGE CCombinedArtifactInstance : public GameCallbackHolder
 {
 protected:
 	using GameCallbackHolder::GameCallbackHolder;
+
 public:
-	using ArtPlacementMap = std::map<const CArtifactInstance*, ArtifactPosition>;
+	using ArtPlacementMap = std::map<const CArtifactInstance *, ArtifactPosition>;
 
-	struct PartInfo : public GameCallbackHolder
+	struct PartInfo
 	{
-		explicit PartInfo(IGameCallback * cb);
+	private:
+		const CArtifactInstance * artifactPtr = nullptr;
+		ArtifactInstanceID artifactID;
+	public:
+
+		PartInfo() = default;
 		PartInfo(const CArtifactInstance * artifact, ArtifactPosition slot);
 
-		ArtifactInstanceID artifactID;
 		ArtifactPosition slot;
 
 		const CArtifactInstance * getArtifact() const;
+		ArtifactInstanceID getArtifactID() const;
 
 		template <typename Handler>
 		void serialize(Handler & h);

+ 1 - 1
lib/entities/artifact/CArtifactSet.cpp

@@ -281,7 +281,7 @@ bool CArtifactSet::isPositionFree(const ArtifactPosition & pos, bool onlyLockChe
 		return artifactsInBackpack.size() < GameConstants::ALTAR_ARTIFACTS_SLOTS;
 
 	if(const ArtSlotInfo *s = getSlot(pos))
-		return (onlyLockCheck || !s->getArt()) && !s->locked;
+		return (onlyLockCheck || !s->getID().hasValue()) && !s->locked;
 
 	return true; //no slot means not used
 }

+ 0 - 3
lib/gameState/CGameState.cpp

@@ -1569,9 +1569,6 @@ void CGameState::buildBonusSystemTree()
 	buildGlobalTeamPlayerTree();
 	for(auto & armed : map->getObjects<CArmedInstance>())
 		armed->attachToBonusSystem(*this);
-
-	for(auto & art : map->getArtifacts())
-		art->attachToBonusSystem(*this);
 }
 
 void CGameState::restoreBonusSystemTree()

+ 1 - 1
lib/mapping/CMap.cpp

@@ -873,7 +873,7 @@ const std::vector<ObjectInstanceID> & CMap::getHeroesOnMap()
 void CMap::addToHeroPool(std::shared_ptr<CGHeroInstance> hero)
 {
 	assert(hero->getHeroTypeID().isValid());
-	assert(!vstd::contains(heroesOnMap, hero->getHeroTypeID()));
+	assert(!vstd::contains(heroesOnMap, hero->id));
 	assert(heroesPool.at(hero->getHeroTypeID().getNum()) == nullptr);
 
 	heroesPool.at(hero->getHeroTypeID().getNum()) = hero;