Преглед на файлове

Finally working hero crossover in campaigns.
Uncovered new secrets of h3m.

Michał W. Urbańczyk преди 12 години
родител
ревизия
13b3d23b26
променени са 8 файла, в които са добавени 75 реда и са изтрити 65 реда
  1. 5 0
      client/NetPacksClient.cpp
  2. 34 64
      lib/CGameState.cpp
  3. 1 1
      lib/CObjectHandler.cpp
  4. 10 0
      lib/Connection.cpp
  5. 2 0
      lib/Connection.h
  6. 10 0
      lib/NetPacks.h
  7. 1 0
      lib/RegisterTypes.h
  8. 12 0
      server/CGameHandler.cpp

+ 5 - 0
client/NetPacksClient.cpp

@@ -317,6 +317,11 @@ void UpdateCampaignState::applyCl( CClient *cl )
 		cl->finishCampaign(camp);
 }
 
+void PrepareForAdvancingCampaign::applyCl(CClient *cl)
+{
+	cl->serv->prepareForSendingHeroes();
+}
+
 void RemoveObject::applyFirstCl( CClient *cl )
 {
 	const CGObjectInstance *o = cl->getObj(id);

+ 34 - 64
lib/CGameState.cpp

@@ -1237,6 +1237,40 @@ void CGameState::init(StartInfo * si)
 
 	/*************************HEROES************************************************/
 	tlog4 << "\tSetting up heroes";
+	//Replace placeholders with heroes from previous missions
+	BOOST_FOREACH(auto obj, campHeroReplacements)
+	{
+		CGHeroPlaceholder *placeholder = dynamic_cast<CGHeroPlaceholder*>(&*map->objects[obj.second]);
+
+		CGHeroInstance *heroToPlace = obj.first;
+		heroToPlace->id = obj.second;
+		heroToPlace->tempOwner = placeholder->tempOwner;
+		heroToPlace->pos = placeholder->pos;
+		heroToPlace->type = VLC->heroh->heroes[heroToPlace->type->ID];
+
+		BOOST_FOREACH(auto &&i, heroToPlace->stacks)
+			i.second->type = VLC->creh->creatures[i.second->getCreatureID()];
+
+		auto fixArtifact = [&](CArtifactInstance * art)
+		{
+			art->artType = VLC->arth->artifacts[art->artType->id];
+			gs->map->artInstances.push_back(art);
+			art->id = gs->map->artInstances.size() - 1;
+		};
+
+		BOOST_FOREACH(auto &&i, heroToPlace->artifactsWorn)
+			fixArtifact(i.second.artifact);
+		BOOST_FOREACH(auto &&i, heroToPlace->artifactsInBackpack)
+			fixArtifact(i.artifact);
+
+		map->heroes.push_back(heroToPlace);
+		map->objects[heroToPlace->id] = heroToPlace;
+		map->addBlockVisTiles(heroToPlace);
+
+		//const auto & travelOptions = scenarioOps->campState->getCurrentScenario().travelOptions;
+	}
+
+
 	std::set<int> hids; //hero ids to create pool
 
 	for(ui32 i=0; i<map->allowedHeroes.size(); i++) //add to hids all allowed heroes
@@ -1256,71 +1290,7 @@ void CGameState::init(StartInfo * si)
 		hids.erase(vhi->subID);
 	}
 
-	BOOST_FOREACH(auto obj, campHeroReplacements)
-	{
-		CGHeroInstance * hero = new CGHeroInstance();
-		CGHeroInstance * oldHero = obj.first;
-		hero->initHero(oldHero->subID);
-		hero->id = obj.second;
-		map->objects[hero->id] = hero;
-		map->heroes.push_back(hero);
-		const auto & travelOptions = scenarioOps->campState->getCurrentScenario().travelOptions;
 
-		if (travelOptions.whatHeroKeeps & 1)
-		{
-			//giving exp
-			hero->exp = oldHero->exp;
-		}
-		if (travelOptions.whatHeroKeeps & 2)
-		{
-			//giving prim skills
-			for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
-			{
-				hero->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL) &&
-					Selector::subtype(g) && Selector::sourceType(Bonus::HERO_BASE_SKILL) )->val
-					= oldHero->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL) &&
-						Selector::subtype(g) && Selector::sourceType(Bonus::HERO_BASE_SKILL) )->val;
-			}
-		}
-		if (travelOptions.whatHeroKeeps & 4)
-		{
-			//giving sec skills
-			hero->secSkills = oldHero->secSkills;
-		}
-		if (travelOptions.whatHeroKeeps & 8)
-		{
-			//giving spells
-			hero->spells = oldHero->spells;
-		}
-		if (travelOptions.whatHeroKeeps & 16)
-		{
-			//giving artifacts
-			size_t totalArts = GameConstants::BACKPACK_START + oldHero->artifactsInBackpack.size();
-			for (size_t i=0; i<totalArts; i++ )
-			{
-				const ArtSlotInfo *info = oldHero->getSlot(static_cast<ArtifactPosition::ArtifactPosition>(i));
-				if (!info)
-					continue;
-
-				const CArtifactInstance *art = info->artifact;
-				if (!art)//FIXME: check spellbook and catapult behaviour
-					continue;
-
-				int id  = art->artType->id;
-				assert( 8*18 > id );//number of arts that fits into h3m format
-				bool takeable = travelOptions.artifsKeptByHero[id / 8] & ( 1 << (id%8) );
-				auto slot = static_cast<ArtifactPosition::ArtifactPosition>(i);
-				if (takeable)
-					hero->setNewArtSlot(slot, const_cast<CArtifactInstance*>(oldHero->getSlot(slot)->artifact.get()), false);
-			}
-		}
-
-		//giving creatures
-		if(!oldHero->stacks.empty())
-		{
-			hero->stacks = oldHero->stacks;
-		}
-	}
 
 	BOOST_FOREACH(auto obj, map->objects) //prisons
 	{

+ 1 - 1
lib/CObjectHandler.cpp

@@ -783,7 +783,7 @@ void CGHeroInstance::initHero()
 		level = 1;
 	}
 
-	if (VLC->modh->modules.COMMANDERS)
+	if (VLC->modh->modules.COMMANDERS && !commander)
 	{
 		commander = new CCommanderInstance (VLC->townh->factions[type->heroClass->faction].commander);
 		commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders

+ 10 - 0
lib/Connection.cpp

@@ -273,6 +273,16 @@ void CConnection::enableSmartPointerSerializatoin()
 	COSer<CConnection>::smartPointerSerialization = true;
 }
 
+void CConnection::prepareForSendingHeroes()
+{
+	loadedPointers.clear();
+	savedPointers.clear();
+	CISer<CConnection>::smartVectorMembersSerialization = false;
+	COSer<CConnection>::smartVectorMembersSerialization = false;
+	CISer<CConnection>::smartPointerSerialization = true;
+	COSer<CConnection>::smartPointerSerialization = true;
+}
+
 CSaveFile::CSaveFile( const std::string &fname )
 {
 	registerTypes(*this);

+ 2 - 0
lib/Connection.h

@@ -1268,6 +1268,8 @@ public:
 	void enableStackSendingByID();
 	void disableSmartPointerSerialization();
 	void enableSmartPointerSerializatoin();
+
+	void prepareForSendingHeroes(); //disables sending vectorised, enables smart pointer serialization, clears saved/loaded ptr cache
 };
 
 DLL_LINKAGE std::ostream &operator<<(std::ostream &str, const CConnection &cpc);

+ 10 - 0
lib/NetPacks.h

@@ -572,6 +572,16 @@ struct AddQuest : public CPackForClient //121
 	}
 };
 
+struct PrepareForAdvancingCampaign : public CPackForClient //122
+{
+	PrepareForAdvancingCampaign() {type = 122;}
+
+	void applyCl(CClient *cl);
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+	}
+};
+
 struct RemoveObject : public CPackForClient //500
 {
 	RemoveObject(){type = 500;};

+ 1 - 0
lib/RegisterTypes.h

@@ -137,6 +137,7 @@ void registerTypes2(Serializer &s)
 	s.template registerType<PlayerEndsGame>();
 	s.template registerType<RemoveBonus>();
 	s.template registerType<UpdateCampaignState>();
+	s.template registerType<PrepareForAdvancingCampaign>();
 	s.template registerType<RemoveObject>();
 	s.template registerType<TryMoveHero>();
 	//s.template registerType<SetGarrisons>();

+ 12 - 0
server/CGameHandler.cpp

@@ -5027,6 +5027,7 @@ void CGameHandler::checkLossVictory( TPlayerColor player )
 	InfoWindow iw;
 	getLossVicMessage(player, vic ? vic : loss , vic, iw);
 	sendAndApply(&iw);
+
 	PlayerEndsGame peg;
 	peg.player = player;
 	peg.victory = vic;
@@ -5081,6 +5082,17 @@ void CGameHandler::checkLossVictory( TPlayerColor player )
 			}
 			gs->scenarioOps->campState->mapConquered(hes);
 
+			//Request clients to change connection mode
+			PrepareForAdvancingCampaign pfac;
+			sendAndApply(&pfac);
+			//Change connection mode
+			if(getPlayer(player)->human && getStartInfo()->campState)
+			{
+				BOOST_FOREACH(auto connection, conns)
+					connection->prepareForSendingHeroes();
+			}
+
+
 			UpdateCampaignState ucs;
 			ucs.camp = gs->scenarioOps->campState;
 			sendAndApply(&ucs);