Przeglądaj źródła

- linux fix for BuildingHandler
- #584 should be fixed

- first part of ally support:
-- shared FoW
-- function Callback::getPlayerRelations for team checking

Ivan Savenko 15 lat temu
rodzic
commit
3c868146a6

+ 1 - 1
CCallback.cpp

@@ -315,7 +315,7 @@ bool CCallback::verifyPath(CPath * path, bool blockSea) const
 std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibilityMap() const
 {
 	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
-	return gs->players[player].fogOfWarMap;
+	return gs->getPlayerTeam(player)->fogOfWarMap;
 }
 
 

+ 3 - 3
client/CMessage.cpp

@@ -157,13 +157,13 @@ std::vector<std::string> CMessage::breakText( std::string text, size_t maxLineSi
 			else 
 			{
 			/* TODO: boost should have a nice method to do that. */
-				while(pos > 0 &&
-					  text[pos] != ' ' && 
+				while(pos > 0 && text[pos]>' ')
+					/*  text[pos] != ' ' && 
 					  text[pos] != ',' &&
 					  text[pos] != '.' &&
 					  text[pos] != ';' &&
 					  text[pos] != '!' &&
-					  text[pos] != '?')
+					  text[pos] != '?')*/
 					pos --;
 			}
 			if (pos > 0)

+ 7 - 6
client/NetPacksClient.cpp

@@ -194,7 +194,7 @@ void RemoveObject::applyFirstCl( CClient *cl )
 	for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
 	{
 		if(i->first >= PLAYER_LIMIT) continue;
-		if(GS(cl)->players[i->first].fogOfWarMap[pos.x][pos.y][pos.z])
+		if(GS(cl)->getPlayerTeam(i->first)->fogOfWarMap[pos.x][pos.y][pos.z])
 		{
 			i->second->objectRemoved(o);
 		}
@@ -216,8 +216,9 @@ void TryMoveHero::applyFirstCl( CClient *cl )
 	{
 		if(i->first >= PLAYER_LIMIT)
 			continue;
-		PlayerState &p = GS(cl)->players[i->first];
-		if((p.fogOfWarMap[start.x-1][start.y][start.z] || p.fogOfWarMap[end.x-1][end.y][end.z]) && p.human)
+		TeamState *t = GS(cl)->getPlayerTeam(i->first);
+		if((t->fogOfWarMap[start.x-1][start.y][start.z] || t->fogOfWarMap[end.x-1][end.y][end.z])
+				&& GS(cl)->getPlayer(i->first)->human)
 			humanKnows = true;
 	}
 
@@ -250,8 +251,8 @@ void TryMoveHero::applyCl( CClient *cl )
 	for(std::map<ui8, CGameInterface*>::iterator i=cl->playerint.begin();i!=cl->playerint.end();i++)
 	{
 		if(i->first >= PLAYER_LIMIT) continue;
-		PlayerState &p = GS(cl)->players[i->first];
-		if(p.fogOfWarMap[start.x-1][start.y][start.z] || p.fogOfWarMap[end.x-1][end.y][end.z])
+		TeamState *t = GS(cl)->getPlayerTeam(i->first);
+		if(t->fogOfWarMap[start.x-1][start.y][start.z] || t->fogOfWarMap[end.x-1][end.y][end.z])
 		{
 			i->second->heroMoved(*this);
 		}
@@ -786,7 +787,7 @@ void NewObject::applyCl(CClient *cl)
 	{
 		//TODO: check if any covered tile is visible
 		if(i->first >= PLAYER_LIMIT) continue;
-		if(GS(cl)->players[i->first].fogOfWarMap[obj->pos.x][obj->pos.y][obj->pos.z])
+		if(GS(cl)->getPlayerTeam(i->first)->fogOfWarMap[obj->pos.x][obj->pos.y][obj->pos.z])
 		{
 			i->second->newObject(obj);
 		}

+ 1 - 1
hch/CBuildingHandler.cpp

@@ -145,7 +145,7 @@ void CBuildingHandler::loadBuildings()
 	}
 
 	//loading ERMU to picture
-	std::ifstream etp("config/ERMU_to_picture.txt");
+	std::ifstream etp(DATA_DIR "/config/ERMU_to_picture.txt");
 
 	assert(etp.is_open());
 

+ 3 - 4
hch/CObjectHandler.cpp

@@ -435,9 +435,9 @@ void CGObjectInstance::getSightTiles(std::set<int3> &tiles) const //returns refe
 }
 void CGObjectInstance::hideTiles(int ourplayer, int radius) const
 {
-	for (std::map<ui8, PlayerState>::iterator i = cb->gameState()->players.begin(); i != cb->gameState()->players.end(); i++)
+	for (std::map<ui8, TeamState>::iterator i = cb->gameState()->teams.begin(); i != cb->gameState()->teams.end(); i++)
 	{
-		if (ourplayer != i->first && i->second.status == PlayerState::INGAME) //TODO: team support
+		if ( !vstd::contains(i->second.players, ourplayer )/* && i->second.status == PlayerState::INGAME*/)
 		{
 			FoWChange fw;
 			fw.mode = 0;
@@ -923,8 +923,7 @@ void CGHeroInstance::onHeroVisit(const CGHeroInstance * h) const
 
 	if (ID == HEROI_TYPE) //hero
 	{
-		//TODO: check for allies
-		if(tempOwner == h->tempOwner) //our hero
+		if( cb->getPlayerRelations(tempOwner, h->tempOwner)) //our or ally hero
 		{
 			//exchange
 			cb->heroExchange(id, h->id);

+ 47 - 9
lib/CGameState.cpp

@@ -1394,6 +1394,8 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 		std::pair<int,PlayerState> ins(it->first,PlayerState());
 		ins.second.color=ins.first;
 		ins.second.human = it->second.human;
+		ins.second.team = map->players[ins.first].team;
+		teams[ins.second.team].players.insert(ins.first);
 		players.insert(ins);
 	}
 
@@ -1608,8 +1610,8 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 		}
 	}
 
-	/*************************FOG**OF**WAR******************************************/		
-	for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
+	/*************************FOG**OF**WAR******************************************/
+	for(std::map<ui8, TeamState>::iterator k=teams.begin(); k!=teams.end(); ++k)
 	{
 		k->second.fogOfWarMap.resize(map->width);
 		for(int g=0; g<map->width; ++g)
@@ -1626,7 +1628,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 
 		BOOST_FOREACH(CGObjectInstance *obj, map->objects)
 		{
-			if(obj->tempOwner != k->first) continue; //not a flagged object
+			if( !vstd::contains(k->second.players, obj->tempOwner)) continue; //not a flagged object
 
 			std::set<int3> tiles;
 			obj->getSightTiles(tiles);
@@ -1635,7 +1637,10 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 				k->second.fogOfWarMap[tile.x][tile.y][tile.z] = 1;
 			}
 		}
-
+	}
+	
+	for(std::map<ui8, PlayerState>::iterator k=players.begin(); k!=players.end(); ++k)
+	{
 		//starting bonus
 		if(si->playerInfos[k->first].bonus==PlayerSettings::brandom)
 			si->playerInfos[k->first].bonus = ran()%3;
@@ -2225,6 +2230,28 @@ void CGameState::apply(CPack *pack)
 	applierGs->apps[typ]->applyOnGS(this,pack);
 }
 
+TeamState *CGameState::getTeam(ui8 teamID)
+{
+	if(vstd::contains(teams,teamID))
+	{
+		return &teams[teamID];
+	}
+	else 
+	{
+		tlog2 << "Warning: Cannot find info for team " << int(teamID) << std::endl;
+		return NULL;
+	}
+	
+}
+
+TeamState *CGameState::getPlayerTeam(ui8 color)
+{
+	PlayerState * ps = getPlayer(color);
+	if (ps)
+		return getTeam(ps->team);
+	return NULL;
+}
+
 PlayerState * CGameState::getPlayer( ui8 color, bool verbose )
 {
 	if(vstd::contains(players,color))
@@ -2244,6 +2271,17 @@ const PlayerState * CGameState::getPlayer( ui8 color, bool verbose ) const
 	return (const_cast<CGameState *>(this))->getPlayer(color, verbose);
 }
 
+
+const TeamState * CGameState::getTeam( ui8 teamID ) const
+{
+	return (const_cast<CGameState *>(this))->getTeam(teamID);
+}
+
+const TeamState * CGameState::getPlayerTeam( ui8 teamID ) const
+{
+	return (const_cast<CGameState *>(this))->getPlayerTeam(teamID);
+}
+
 bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath &ret)
 {
 	if(!map->isInTheMap(src) || !map->isInTheMap(dest)) //check input
@@ -2261,7 +2299,7 @@ bool CGameState::getPath(int3 src, int3 dest, const CGHeroInstance * hero, CPath
 // 	else
 // 		blockLandSea = boost::logic::indeterminate;
 
-	const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayer(hero->tempOwner)->fogOfWarMap;
+	const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayerTeam(hero->tempOwner)->fogOfWarMap;
 
 	//graph initialization
 	std::vector< std::vector<CPathNode> > graph;
@@ -2407,7 +2445,7 @@ void CGameState::calculatePaths(const CGHeroInstance *hero, CPathsInfo &out, int
 	else
 		onLand = boost::logic::indeterminate;
 
-	const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayer(hero->tempOwner)->fogOfWarMap;
+	const std::vector<std::vector<std::vector<ui8> > > &FoW = getPlayerTeam(hero->tempOwner)->fogOfWarMap;
 
 	bool flying = hero->hasBonusOfType(Bonus::FLYING_MOVEMENT);
 	bool waterWalk = hero->hasBonusOfType(Bonus::WATER_WALKING);
@@ -2654,7 +2692,7 @@ bool CGameState::isVisible(int3 pos, int player)
 {
 	if(player == 255) //neutral player
 		return false;
-	return players[player].fogOfWarMap[pos.x][pos.y][pos.z];
+	return getPlayerTeam(player)->fogOfWarMap[pos.x][pos.y][pos.z];
 }
 
 bool CGameState::isVisible( const CGObjectInstance *obj, int player )
@@ -3434,9 +3472,9 @@ ui8 CGameState::checkForStandardWin() const
 			{
 				//first player remaining ingame - candidate for victory
 				supposedWinner = i->second.color;
-				winnerTeam = map->players[supposedWinner].team;
+				winnerTeam = i->second.team;
 			}
-			else if(winnerTeam != map->players[i->second.color].team)
+			else if(winnerTeam != i->second.team)
 			{
 				//current candidate has enemy remaining in game -> no vicotry
 				return 255;

+ 24 - 2
lib/CGameState.h

@@ -120,7 +120,8 @@ public:
 	ui8 color;
 	ui8 human; //true if human controlled player, false for AI
 	ui32 currentSelection; //id of hero/town, 0xffffffff if none
-	std::vector<std::vector<std::vector<ui8> > >  fogOfWarMap; //true - visible, false - hidden
+	ui8 team;
+	//std::vector<std::vector<std::vector<ui8> > > * fogOfWarMap; //pointer to team's fog of war
 	std::vector<si32> resources;
 	std::vector<CGHeroInstance *> heroes;
 	std::vector<CGTownInstance *> towns;
@@ -139,13 +140,29 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & color & human & currentSelection & fogOfWarMap & resources & status;
+		h & color & human & currentSelection & team & resources & status;
 		h & heroes & towns & availableHeroes & dwellings & bonuses & status & daysWithoutCastle;
 		h & enteredLosingCheatCode & enteredWinningCheatCode;
 		h & static_cast<CBonusSystemNode&>(*this);
 	}
 };
 
+struct DLL_EXPORT TeamState : public CBonusSystemNode
+{
+public:
+	std::set<ui8> players; // members of this team
+	std::vector<std::vector<std::vector<ui8> > >  fogOfWarMap; //true - visible, false - hidden
+	
+	//TeamState();
+	
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & players & fogOfWarMap;
+		h & static_cast<CBonusSystemNode&>(*this);
+	}
+
+};
+
 struct DLL_EXPORT CObstacleInstance
 {
 	int uniqueID;
@@ -384,6 +401,7 @@ public:
 	ui32 day; //total number of days in game
 	Mapa * map;
 	std::map<ui8, PlayerState> players; //ID <-> player state
+	std::map<ui8, TeamState> teams; //ID <-> team state
 	std::map<int, CGDefInfo*> villages, forts, capitols; //def-info for town graphics
 	CBonusSystemNode globalEffects;
 
@@ -402,7 +420,11 @@ public:
 
 	boost::shared_mutex *mx;
 	PlayerState *getPlayer(ui8 color, bool verbose = true);
+	TeamState *getTeam(ui8 teamID);//get team by team ID
+	TeamState *getPlayerTeam(ui8 color);// get team by player color
 	const PlayerState *getPlayer(ui8 color, bool verbose = true) const;
+	const TeamState *getTeam(ui8 teamID) const;
+	const TeamState *getPlayerTeam(ui8 color) const;
 	void init(StartInfo * si, ui32 checksum, int Seed);
 	void loadTownDInfos();
 	void randomizeObject(CGObjectInstance *cur);

+ 15 - 3
lib/IGameCallback.cpp

@@ -107,7 +107,7 @@ void IGameCallback::getTilesInRange( std::set<int3> &tiles, int3 pos, int radiou
 		getAllTiles (tiles, player, -1, 0);
 	else
 	{
-		PlayerState * plr = &gs->players.find(player)->second;
+		const TeamState * team = gs->getPlayerTeam(player);
 		for (int xd = std::max<int>(pos.x - radious , 0); xd <= std::min<int>(pos.x + radious, gs->map->width - 1); xd++)
 		{
 			for (int yd = std::max<int>(pos.y - radious, 0); yd <= std::min<int>(pos.y + radious, gs->map->height - 1); yd++)
@@ -116,8 +116,8 @@ void IGameCallback::getTilesInRange( std::set<int3> &tiles, int3 pos, int radiou
 				if(distance <= radious)
 				{
 					if(player < 0 
-						|| (mode == 1  && plr->fogOfWarMap[xd][yd][pos.z]==0)
-						|| (mode == -1 && plr->fogOfWarMap[xd][yd][pos.z]==1)
+						|| (mode == 1  && team->fogOfWarMap[xd][yd][pos.z]==0)
+						|| (mode == -1 && team->fogOfWarMap[xd][yd][pos.z]==1)
 					)
 						tiles.insert(int3(xd,yd,pos.z));
 				}
@@ -239,6 +239,18 @@ const PlayerState * IGameCallback::getPlayerState( int color )
 	return gs->getPlayer(color, false);
 }
 
+int IGameCallback::getPlayerRelations( ui8 color1, ui8 color2 )
+{
+	if ( color1 == color2 )
+		return 2;
+	if ( color1 == 255 || color2 == 255)
+		return 0;
+	const TeamState * ts = gs->getPlayerTeam(color1);
+	if (ts && vstd::contains(ts->players, color2))
+		return 1;
+	return 0;
+}
+
 const CTown * IGameCallback::getNativeTown(int color)
 {
 	return &VLC->townh->towns[gs->scenarioOps->getIthPlayersSettings(color).castle];

+ 1 - 0
lib/IGameCallback.h

@@ -68,6 +68,7 @@ public:
 	virtual int3 getMapSize(); //returns size of the map
 	virtual TerrainTile * getTile(int3 pos);
 	virtual const PlayerState * getPlayerState(int color);
+	virtual int getPlayerRelations(ui8 color1, ui8 color2);// -1 = enemy, 0 = neutral, 1 = ally, 2 = same player
 	virtual const CTown *getNativeTown(int color);
 
 	//do sth

+ 8 - 6
lib/NetPacksLib.cpp

@@ -143,14 +143,15 @@ DLL_EXPORT void SetMovePoints::applyGs( CGameState *gs )
 
 DLL_EXPORT void FoWChange::applyGs( CGameState *gs )
 {
-		BOOST_FOREACH(int3 t, tiles)
-		gs->getPlayer(player)->fogOfWarMap[t.x][t.y][t.z] = mode;
+	TeamState * team = gs->getPlayerTeam(player);
+	BOOST_FOREACH(int3 t, tiles)
+		team->fogOfWarMap[t.x][t.y][t.z] = mode;
 	if (mode == 0) //do not hide too much
 	{
 		std::set<int3> tilesRevealed;
 		for (size_t i = 0; i < gs->map->objects.size(); i++)
 		{
-			if(gs->map->objects[i] && gs->map->objects[i]->tempOwner == player) //check owned observators
+			if (gs->map->objects[i])
 			{
 				switch(gs->map->objects[i]->ID)
 				{
@@ -158,13 +159,14 @@ DLL_EXPORT void FoWChange::applyGs( CGameState *gs )
 				case 53://mine
 				case 98://town
 				case 220:
-					gs->map->objects[i]->getSightTiles(tilesRevealed);
+					if(vstd::contains(team->players, player)) //check owned observators
+						gs->map->objects[i]->getSightTiles(tilesRevealed);
 					break;
 				}
 			}
 		}
 		BOOST_FOREACH(int3 t, tilesRevealed) //probably not the most optimal solution ever
-			gs->getPlayer(player)->fogOfWarMap[t.x][t.y][t.z] = 1;
+			team->fogOfWarMap[t.x][t.y][t.z] = 1;
 	}
 }
 DLL_EXPORT void SetAvailableHeroes::applyGs( CGameState *gs )
@@ -377,7 +379,7 @@ void TryMoveHero::applyGs( CGameState *gs )
 	}
 
 	BOOST_FOREACH(int3 t, fowRevealed)
-		gs->getPlayer(h->getOwner())->fogOfWarMap[t.x][t.y][t.z] = 1;
+		gs->getPlayerTeam(h->getOwner())->fogOfWarMap[t.x][t.y][t.z] = 1;
 }
 
 DLL_EXPORT void SetGarrisons::applyGs( CGameState *gs )

+ 2 - 6
server/CGameHandler.cpp

@@ -1888,12 +1888,11 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 			{
 				CGHeroInstance *dh = static_cast<CGHeroInstance *>(obj);
 
-				if(obj->tempOwner==h->tempOwner) 
+				if( getPlayerRelations(dh->tempOwner, h->tempOwner)) 
 				{
 					heroExchange(dh->id, h->id);
 					return true;
 				}
-				//TODO: check for ally
 				startBattleI(h, dh);
 				return true;
 			}
@@ -3357,10 +3356,8 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
 	}
 	if (!army)
 		COMPLAIN_RET("Incorrect call to transform in undead!");
-	tlog1<<"test2\n";
 	if(!vstd::contains(army->Slots(), slot))
 		COMPLAIN_RET("Army doesn't have any creature in that slot!");
-	tlog1<<"test3\n";
 	const CStackInstance &s = army->getStack(slot);
 	int resCreature;//resulting creature - bone dragons or skeletons
 	
@@ -3368,7 +3365,6 @@ bool CGameHandler::transformInUndead(const IMarket *market, const CGHeroInstance
 		resCreature = 68;
 	else
 		resCreature = 56;
-	tlog1<<"test4\n";
 	SetGarrisons sg;
 	sg.garrs[army->id] = army->getArmy();
 	sg.garrs[army->id].setCreature(slot, resCreature, s.count);
@@ -3913,7 +3909,7 @@ void CGameHandler::playerMessage( ui8 player, const std::string &message )
 		for(int i=0;i<gs->map->width;i++)
 			for(int j=0;j<gs->map->height;j++)
 				for(int k=0;k<gs->map->twoLevel+1;k++)
-					if(!gs->getPlayer(fc.player)->fogOfWarMap[i][j][k])
+					if(!gs->getPlayerTeam(fc.player)->fogOfWarMap[i][j][k])
 						fc.tiles.insert(int3(i,j,k));
 		sendAndApply(&fc);
 	}