Browse Source

Preparing crossover heroes works on deep copies of heroes, so the original post-mission state is not lost in the process.

Michał W. Urbańczyk 11 năm trước cách đây
mục cha
commit
d6f8a6d4bf
1 tập tin đã thay đổi với 18 bổ sung3 xóa
  1. 18 3
      lib/CGameState.cpp

+ 18 - 3
lib/CGameState.cpp

@@ -1232,13 +1232,26 @@ CGameState::CrossoverHeroesList CGameState::getCrossoverHeroesFromPreviousScenar
 		}
 		}
 	}
 	}
 
 
-	return std::move(crossoverHeroes);
+	// Now we need to perform deep copies of all heroes
+	// The lambda below replaces pointer to a hero with a pointer to its deep copy.
+	auto replaceWithDeepCopy = [](CGHeroInstance *&hero)
+	{
+		// We cache map original hero => copy.
+		// We may be called multiple times with the same hero and should return a single copy.
+		static std::map<CGHeroInstance*, CGHeroInstance*> oldToCopy;
+		if(!oldToCopy[hero])
+			oldToCopy[hero] = CMemorySerializer::deepCopy(*hero).release();
+
+		hero = oldToCopy[hero];
+	};
+	range::for_each(crossoverHeroes.heroesFromAnyPreviousScenarios, replaceWithDeepCopy);
+	range::for_each(crossoverHeroes.heroesFromPreviousScenario,     replaceWithDeepCopy);
+
+	return crossoverHeroes;
 }
 }
 
 
 void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const
 void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroReplacement> & campaignHeroReplacements, const CScenarioTravel & travelOptions) const
 {
 {
-	//TODO deep copy hero instances
-
 	// create heroes list for convenience iterating
 	// create heroes list for convenience iterating
 	std::vector<CGHeroInstance *> crossoverHeroes;
 	std::vector<CGHeroInstance *> crossoverHeroes;
 	for(auto & campaignHeroReplacement : campaignHeroReplacements)
 	for(auto & campaignHeroReplacement : campaignHeroReplacements)
@@ -1246,6 +1259,8 @@ void CGameState::prepareCrossoverHeroes(std::vector<CGameState::CampaignHeroRepl
 		crossoverHeroes.push_back(campaignHeroReplacement.hero);
 		crossoverHeroes.push_back(campaignHeroReplacement.hero);
 	}
 	}
 
 
+	// TODO replace magic numbers with named constants
+	// TODO this logic (what should be kept) should be part of CScenarioTravel and be exposed via some clean set of methods
 	if(!(travelOptions.whatHeroKeeps & 1))
 	if(!(travelOptions.whatHeroKeeps & 1))
 	{
 	{
 		//trimming experience
 		//trimming experience