Kaynağa Gözat

* some work on hero crossover; still buggy

mateuszb 12 yıl önce
ebeveyn
işleme
dc091a1ce1

+ 13 - 0
client/VCMI_client.vcxproj

@@ -92,6 +92,19 @@
     <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='RD|Win32'" />
     <CodeAnalysisRuleAssemblies Condition="'$(Configuration)|$(Platform)'=='RD|x64'" />
   </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
+    <IncludePath>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+    <LibraryPath>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Lib;$(SolutionDir)..\libs\$(PlatformShortName);$(VCMI_Out);$(LibraryPath)</LibraryPath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|Win32'">
+    <IncludePath>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
+    <IncludePath>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+  </PropertyGroup>
+  <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='RD|x64'">
+    <IncludePath>C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;C:\Program Files %28x86%29\Microsoft SDKs\Windows\v7.0A\Include;$(SolutionDir)..\include;$(IncludePath)</IncludePath>
+  </PropertyGroup>
   <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
     <ClCompile>
       <AdditionalOptions>/MP4 %(AdditionalOptions)</AdditionalOptions>

+ 37 - 38
lib/CGameState.cpp

@@ -588,6 +588,9 @@ std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
 				{
 					for(ui32 i=0;i<map->objects.size();i++)
 					{
+						if(!map->objects[i])
+							continue;
+
 						if(map->objects[i]->ID==Obj::RANDOM_TOWN
 							&& dynamic_cast<CGTownInstance*>(map->objects[i].get())->identifier == info->identifier)
 						{
@@ -853,13 +856,6 @@ void CGameState::init(StartInfo * si)
 		return ret;
 	};
 
-	auto replaceHero = [&](int objId, CGHeroInstance * ghi)
-	{
-		ghi->id = objId;
-		gs->map->objects[objId] = ghi;
-		gs->map->heroes.push_back(ghi);
-	};
-
 	tlog0 << "\tUsing random seed: "<< si->seedToBeUsed << std::endl;
 	ran.seed((boost::int32_t)si->seedToBeUsed);
 	scenarioOps = new StartInfo(*si);
@@ -995,7 +991,7 @@ void CGameState::init(StartInfo * si)
 
 		//remove tiles with holes
 		for(ui32 no=0; no<map->objects.size(); ++no)
-			if(map->objects[no]->ID == Obj::HOLE)
+			if(map->objects[no] && map->objects[no]->ID == Obj::HOLE)
 				allowedPos -= map->objects[no]->pos;
 
 		if(allowedPos.size())
@@ -1023,6 +1019,9 @@ void CGameState::init(StartInfo * si)
 	tlog4 << "\tRandomizing objects";
 	BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 	{
+		if(!obj)
+			continue;
+
 		randomizeObject(obj);
 		obj->hoverName = VLC->generaltexth->names[obj->ID];
 
@@ -1095,6 +1094,14 @@ void CGameState::init(StartInfo * si)
 	tlog4 << "\tReplacing hero placeholders";
 	if (scenarioOps->campState)
 	{
+		auto replaceHero = [&](int objId, CGHeroInstance * ghi)
+		{
+			ghi->tempOwner = getHumanPlayerInfo()[0]->color;
+			ghi->id = objId;
+			gs->map->objects[objId] = ghi;
+			gs->map->heroes.push_back(ghi);
+		};
+
 		auto campaign = scenarioOps->campState;
 		auto bonus = campaign->getBonusForCurrentMap();
 
@@ -1158,7 +1165,12 @@ void CGameState::init(StartInfo * si)
 					if(Xheroes.size() > hp->power - 1)
 						replaceHero(g, Xheroes[hp->power - 1]);
 					else
-						tlog2 << "Warning, no hero to replace!\n";
+					{
+						tlog3 << "Warning, no hero to replace!\n";
+						map->removeBlockVisTiles(hp, true);
+						delete hp;
+						map->objects[g] = NULL;
+					}
 					//we don't have to remove hero from Xheroes because it would destroy the order and duplicates shouldn't happen
 				}
 			}
@@ -1235,15 +1247,18 @@ void CGameState::init(StartInfo * si)
 			tlog2 << "Warning - hero with uninitialized owner!\n";
 			continue;
 		}
-		CGHeroInstance * vhi = (map->heroes[i]);
-		vhi->initHero();
-		players.find(vhi->getOwner())->second.heroes.push_back(vhi);
-		hids.erase(vhi->subID);
+		CGHeroInstance * vhi = map->heroes[i];
+		if(vhi->sex == 0xff) //campaign heroes already come initialized -- I hope this will skip them
+		{
+			vhi->initHero();
+			players.find(vhi->getOwner())->second.heroes.push_back(vhi);
+			hids.erase(vhi->subID);
+		}
 	}
 
 	for (ui32 i=0; i<map->objects.size();i++) //prisons
 	{
-		if (map->objects[i]->ID == Obj::PRISON)
+		if (map->objects[i] && map->objects[i]->ID == Obj::PRISON)
 			hids.erase(map->objects[i]->subID);
 	}
 
@@ -1337,7 +1352,7 @@ void CGameState::init(StartInfo * si)
 
 		BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 		{
-			if( !vstd::contains(k->second.players, obj->tempOwner)) continue; //not a flagged object
+			if(!obj || !vstd::contains(k->second.players, obj->tempOwner)) continue; //not a flagged object
 
 			boost::unordered_set<int3, ShashInt3> tiles;
 			obj->getSightTiles(tiles);
@@ -1521,10 +1536,14 @@ void CGameState::init(StartInfo * si)
 	objCaller->preInit();
 	BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 	{
-		obj->initObj();
+		if(obj)
+			obj->initObj();
 	}
 	BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 	{
+		if(!obj)
+			continue;
+
 		switch (obj->ID)
 		{
 			case Obj::QUEST_GUARD:
@@ -1542,7 +1561,7 @@ void CGameState::init(StartInfo * si)
 
 	for(auto k=players.begin(); k!=players.end(); ++k)
 	{
-		if(k->first==255)
+		if(k->first==GameConstants::NEUTRAL_PLAYER)
 			continue;
 
 		//init visiting and garrisoned heroes
@@ -2590,30 +2609,10 @@ void CGameState::giveHeroArtifact(CGHeroInstance *h, int aid)
 	 ai->putAt(ArtifactLocation(h, ai->firstAvailableSlot(h)));
 }
 
-int3 CPath::startPos() const
-{
-	return nodes[nodes.size()-1].coord;
-}
-void CPath::convert(ui8 mode) //mode=0 -> from 'manifest' to 'object'
-{
-	if (mode==0)
-	{
-		for (ui32 i=0;i<nodes.size();i++)
-		{
-			nodes[i].coord = CGHeroInstance::convertPosition(nodes[i].coord,true);
-		}
-	}
-}
-
-int3 CPath::endPos() const
-{
-	return nodes[0].coord;
-}
-
 CGPathNode::CGPathNode()
 :coord(-1,-1,-1)
 {
-	accessible = 0;
+	accessible = NOT_SET;
 	land = 0;
 	moveRemains = 0;
 	turns = 255;

+ 3 - 21
lib/CGameState.h

@@ -222,26 +222,18 @@ struct UpgradeInfo
 	UpgradeInfo(){oldID = -1;};
 };
 
-struct CPathNode
-{
-	bool accessible; //true if a hero can be on this node
-	int dist; //distance from the first node of searching; -1 is infinity
-	CPathNode * theNodeBefore;
-	int3 coord; //coordiantes
-	bool visited;
-};
-
 struct DLL_LINKAGE CGPathNode
 {
 	enum EAccessibility
 	{
-		ACCESSIBLE=1, //tile can be entered and passed
+		NOT_SET = 0,
+		ACCESSIBLE = 1, //tile can be entered and passed
 		VISITABLE, //tile can be entered as the last tile in path
 		BLOCKVIS,  //visitable from neighbouring tile but not passable
 		BLOCKED //tile can't be entered nor visited
 	};
 
-	ui8 accessible; //the enum above
+	EAccessibility accessible;
 	ui8 land;
 	ui8 turns;
 	ui32 moveRemains;
@@ -252,16 +244,6 @@ struct DLL_LINKAGE CGPathNode
 	bool reachable() const;
 };
 
-
-struct DLL_LINKAGE CPath
-{
-	std::vector<CPathNode> nodes; //just get node by node
-
-	int3 startPos() const; // start point
-	int3 endPos() const; //destination point
-	void convert(ui8 mode); //mode=0 -> from 'manifest' to 'object'
-};
-
 struct DLL_LINKAGE CGPath
 {
 	std::vector<CGPathNode> nodes; //just get node by node

+ 0 - 26
lib/IGameCallback.cpp

@@ -424,32 +424,6 @@ std::vector < std::string > CGameInfoCallback::getObjDescriptions(int3 pos) cons
 		ret.push_back(obj->getHoverText());
 	return ret;
 }
-bool CGameInfoCallback::verifyPath(CPath * path, bool blockSea) const
-{
-	for (size_t i=0; i < path->nodes.size(); ++i)
-	{
-		const TerrainTile *t = getTile(path->nodes[i].coord); //current tile
-		ERROR_RET_VAL_IF(!t, "Path contains not visible tile: " << path->nodes[i].coord << "!", false);
-		if (t->blocked && !t->visitable)
-			return false; //path is wrong - one of the tiles is blocked
-
-		if (blockSea)
-		{
-			if (i==0)
-				continue;
-
-			const TerrainTile *prev = getTile(path->nodes[i-1].coord); //tile of previous node on the path
-            if ((   t->terType == ETerrainType::WATER  &&  prev->terType != ETerrainType::WATER)
-                || (t->terType != ETerrainType::WATER  &&  prev->terType == ETerrainType::WATER)
-                ||  prev->terType == ETerrainType::ROCK
-				)
-				return false;
-		}
-
-
-	}
-	return true;
-}
 
 bool CGameInfoCallback::isVisible(int3 pos, int Player) const
 {

+ 0 - 1
lib/IGameCallback.h

@@ -101,7 +101,6 @@ public:
 	bool getHeroInfo(const CGObjectInstance *hero, InfoAboutHero &dest) const;
 	int getSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //when called during battle, takes into account creatures' spell cost reduction
 	int estimateSpellDamage(const CSpell * sp, const CGHeroInstance * hero) const; //estimates damage of given spell; returns 0 if spell causes no dmg
-	bool verifyPath(CPath * path, bool blockSea)const;
 	const CGHeroInstance* getSelectedHero(int player) const; //NULL if no hero is selected
 	const CGHeroInstance* getSelectedHero() const; //of current (active) player
 

+ 8 - 8
server/CGameHandler.cpp

@@ -1170,7 +1170,7 @@ void CGameHandler::newTurn()
 	{
 		BOOST_FOREACH (auto obj, gs->map->objects)
 		{
-			if (obj->ID == Obj::PRISON) //give imprisoned hero 0 exp to level him up. easiest to do at this point
+			if (obj && obj->ID == Obj::PRISON) //give imprisoned hero 0 exp to level him up. easiest to do at this point
 			{
 				changePrimSkill (obj->id, PrimarySkill::EXPERIENCE, 0);
 			}
@@ -5006,7 +5006,7 @@ void CGameHandler::winLoseHandle(ui8 players )
 	}
 }
 
-void CGameHandler::checkLossVictory( ui8 player )
+void CGameHandler::checkLossVictory( TPlayerColor player )
 {
 	const PlayerState *p = gs->getPlayer(player);
 	if(p->status) //player already won / lost
@@ -5046,11 +5046,11 @@ void CGameHandler::checkLossVictory( ui8 player )
 	}
 	else //player lost -> all his objects become unflagged (neutral)
 	{
-		std::vector<ConstTransitivePtr<CGHeroInstance> > hlp = p->heroes;
-		for (std::vector<ConstTransitivePtr<CGHeroInstance> >::const_iterator i = hlp.begin(); i != hlp.end(); i++) //eliminate heroes
+		auto hlp = p->heroes;
+		for (auto i = hlp.cbegin(); i != hlp.cend(); i++) //eliminate heroes
 			removeObject((*i)->id);
 
-		for (std::vector<ConstTransitivePtr<CGObjectInstance> >::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
+		for (auto i = gs->map->objects.cbegin(); i != gs->map->objects.cend(); i++) //unflag objs
 		{
 			if(*i  &&  (*i)->tempOwner == player)
 				setOwner((**i).id,GameConstants::NEUTRAL_PLAYER);
@@ -5060,7 +5060,7 @@ void CGameHandler::checkLossVictory( ui8 player )
 		winLoseHandle(GameConstants::ALL_PLAYERS & ~(1<<player));
 	}
 
-	if(vic)
+	if(vic && p->human)
 	{
 		end2 = true;
 
@@ -5069,7 +5069,7 @@ void CGameHandler::checkLossVictory( ui8 player )
 			std::vector<CGHeroInstance *> hes;
 			BOOST_FOREACH(CGHeroInstance * ghi, gs->map->heroes)
 			{
-				if (ghi->tempOwner == vic)
+				if (ghi->tempOwner == player)
 				{
 					hes.push_back(ghi);
 				}
@@ -5194,7 +5194,7 @@ void CGameHandler::getLossVicMessage( ui8 player, si8 standard, bool victory, In
 
 bool CGameHandler::dig( const CGHeroInstance *h )
 {
-	for (std::vector<ConstTransitivePtr<CGObjectInstance> >::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
+	for (auto i = gs->map->objects.cbegin(); i != gs->map->objects.cend(); i++) //unflag objs
 	{
 		if(*i && (*i)->ID == Obj::HOLE  &&  (*i)->pos == h->getPosition())
 		{

+ 1 - 1
server/CGameHandler.h

@@ -107,7 +107,7 @@ public:
 	int moveStack(int stack, BattleHex dest); //returned value - travelled distance
 	void startBattle(const CArmedInstance *armies[2], int3 tile, const CGHeroInstance *heroes[2], bool creatureBank, boost::function<void(BattleResult*)> cb, const CGTownInstance *town = NULL); //use hero=NULL for no hero
 	void runBattle();
-	void checkLossVictory(ui8 player);
+	void checkLossVictory(TPlayerColor player);
 	void winLoseHandle(ui8 players=255); //players: bit field - colours of players to be checked; default: all
 	void getLossVicMessage(ui8 player, si8 standard, bool victory, InfoWindow &out) const;