2
0
Эх сурвалжийг харах

- Implemented hero recreate handling correctly

beegee1 11 жил өмнө
parent
commit
d0a5a6eab4

+ 2 - 16
lib/CGameState.cpp

@@ -2823,24 +2823,10 @@ std::vector<CGameState::CampaignHeroReplacement> CGameState::generateCampaignHer
 					return hero->subID == heroPlaceholder->subID;
 				});
 
-				CGHeroInstance * hero = nullptr;
-				if(it == crossoverHeroes.heroesFromAnyPreviousScenarios.end())
+				if(it != crossoverHeroes.heroesFromAnyPreviousScenarios.end())
 				{
-					if(scenarioOps->campState->camp->header.mapVersion == 12) // AB:AB campaign
-					{
-						// special case for this campaign, not found heroes will be newly created
-						hero = new CGHeroInstance();
-						hero->initHero(HeroTypeID(heroPlaceholder->subID));
-					}
-				}
-				else
-				{
-					hero = *it;
+					auto hero = *it;
 					crossoverHeroes.removeHeroFromBothLists(hero);
-				}
-
-				if(hero)
-				{
 					campaignHeroReplacements.push_back(CampaignHeroReplacement(hero, heroPlaceholder->id));
 				}
 			}

+ 14 - 0
lib/mapping/CCampaignHandler.cpp

@@ -78,6 +78,20 @@ unique_ptr<CCampaign> CCampaignHandler::getCampaign( const std::string & name )
 		scenarioID++;
 	}
 
+	// handle campaign specific discrepancies
+	if(name == "DATA/AB.H3C")
+	{
+		ret->scenarios[6].keepHeroes.push_back(HeroTypeID(155)); // keep hero Xeron for map 7 To Kill A Hero
+	}
+	else if(name == "DATA/FINAL.H3C")
+	{
+		// keep following heroes for map 8 Final H
+		ret->scenarios[7].keepHeroes.push_back(HeroTypeID(148)); // Gelu
+		ret->scenarios[7].keepHeroes.push_back(HeroTypeID(27)); // Gem
+		ret->scenarios[7].keepHeroes.push_back(HeroTypeID(102)); // Crag Hack
+		ret->scenarios[7].keepHeroes.push_back(HeroTypeID(96)); // Yog
+	}
+
 	return ret;
 }
 

+ 2 - 1
lib/mapping/CCampaignHandler.h

@@ -109,6 +109,7 @@ public:
 	SScenarioPrologEpilog prolog, epilog;
 
 	CScenarioTravel travelOptions;
+	std::vector<HeroTypeID> keepHeroes; // contains list of heroes which should be kept for next scenario (doesn't matter if they lost)
 	std::vector<CGHeroInstance *> crossoverHeroes; // contains all heroes with the same state when the campaign scenario was finished
 	std::vector<CGHeroInstance *> placedCrossoverHeroes; // contains all placed crossover heroes defined by hero placeholders when the scenario was started
 
@@ -120,7 +121,7 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int formatVersion)
 	{
 		h & mapName & scenarioName & packedMapSize & preconditionRegions & regionColor & difficulty & conquered & regionText & 
-			prolog & epilog & travelOptions & crossoverHeroes & placedCrossoverHeroes;
+			prolog & epilog & travelOptions & crossoverHeroes & placedCrossoverHeroes & keepHeroes;
 	}
 };
 

+ 12 - 3
server/CGameHandler.cpp

@@ -5146,12 +5146,21 @@ void CGameHandler::checkVictoryLossConditionsForPlayer(PlayerColor player)
 
 				if(gs->scenarioOps->campState)
 				{
-					std::vector<CGHeroInstance *> heroesBelongingToPlayer;
+					std::vector<CGHeroInstance *> crossoverHeroes;
 					for(CGHeroInstance * hero : gs->map->heroesOnMap)
 					{
-						if(hero->tempOwner == player) heroesBelongingToPlayer.push_back(hero);
+						if(hero->tempOwner == player)
+						{
+							// keep all heroes from the winning player
+							crossoverHeroes.push_back(hero);
+						}
+						else if(vstd::contains(gs->scenarioOps->campState->getCurrentScenario().keepHeroes, HeroTypeID(hero->subID)))
+						{
+							// keep hero whether lost or won (like Xeron in AB campaign)
+							crossoverHeroes.push_back(hero);
+						}
 					}
-					gs->scenarioOps->campState->setCurrentMapAsConquered(heroesBelongingToPlayer);
+					gs->scenarioOps->campState->setCurrentMapAsConquered(crossoverHeroes);
 
 					//Request clients to change connection mode
 					PrepareForAdvancingCampaign pfac;