فهرست منبع

* improvements in battle support - moving creatures work though there are small graphic glitches

* @neweagle - I've replaced in VCMI_Lib.h your #ifndef with #ifdef since you modification affected (and broke) compilation only on MSVC. Is it ok now?
Michał W. Urbańczyk 17 سال پیش
والد
کامیت
a5354271e2
9فایلهای تغییر یافته به همراه303 افزوده شده و 302 حذف شده
  1. 39 47
      CCallback.cpp
  2. 141 248
      CGameState.cpp
  3. 7 1
      CGameState.h
  4. 2 0
      CPlayerInterface.cpp
  5. 13 3
      client/Client.cpp
  6. 22 0
      lib/NetPacks.h
  7. 1 1
      lib/VCMI_Lib.h
  8. 76 2
      server/CGameHandler.cpp
  9. 2 0
      server/CGameHandler.h

+ 39 - 47
CCallback.cpp

@@ -18,6 +18,7 @@
 #include <boost/thread.hpp>
 #include <boost/foreach.hpp>
 #include "lib/NetPacks.h"
+#include <boost/thread/shared_mutex.hpp>
 #ifdef min
 #undef min
 #endif
@@ -53,7 +54,7 @@ bool CCallback::moveHero(int ID, CPath * path, int idtype, int pathType)
 	else //idtype==1; player<0
 	{
 
-		for(std::map<ui8, PlayerState>::iterator j=CGI->state->players.begin(); j!=CGI->state->players.end(); ++j)
+		for(std::map<ui8, PlayerState>::iterator j=gs->players.begin(); j!=gs->players.end(); ++j)
 		{
 			for (int i=0; i<(*j).second.heroes.size();i++)
 			{
@@ -264,10 +265,12 @@ const CGTownInstance * CCallback::getTownInfo(int val, bool mode) //mode = 0 ->
 }
 int CCallback::howManyHeroes()
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->players[player].heroes.size();
 }
 const CGHeroInstance * CCallback::getHeroInfo(int player, int val, bool mode) //mode = 0 -> val = serial; mode = 1 -> val = ID
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	if (gs->currentPlayer!=player) //TODO: checking if we are allowed to give that info
 		return NULL;
 	if (!mode)
@@ -287,41 +290,22 @@ const CGHeroInstance * CCallback::getHeroInfo(int player, int val, bool mode) //
 
 int CCallback::getResourceAmount(int type)
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->players[player].resources[type];
 }
 std::vector<si32> CCallback::getResourceAmount()
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->players[player].resources;
 }
 int CCallback::getDate(int mode)
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->getDate(mode);
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
 }
 std::vector < std::string > CCallback::getObjDescriptions(int3 pos)
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	std::vector<std::string> ret;
 	BOOST_FOREACH(const CGObjectInstance * obj, gs->map->terrain[pos.x][pos.y][pos.z].blockingObjects)
 		ret.push_back(obj->hoverName);
@@ -362,17 +346,20 @@ bool CCallback::verifyPath(CPath * path, bool blockSea)
 
 std::vector< std::vector< std::vector<unsigned char> > > & CCallback::getVisibilityMap()
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->players[player].fogOfWarMap;
 }
 
 
 bool CCallback::isVisible(int3 pos, int Player)
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->players[Player].fogOfWarMap[pos.x][pos.y][pos.z];
 }
 
 std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur)
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	std::vector < const CGTownInstance *> ret = std::vector < const CGTownInstance *>();
 	for ( std::map<ui8, PlayerState>::iterator i=gs->players.begin() ; i!=gs->players.end();i++)
 	{
@@ -388,6 +375,7 @@ std::vector < const CGTownInstance *> CCallback::getTownsInfo(bool onlyOur)
 }
 std::vector < const CGHeroInstance *> CCallback::getHeroesInfo(bool onlyOur)
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	std::vector < const CGHeroInstance *> ret;
 	for(int i=0;i<gs->map->heroes.size();i++)
 	{
@@ -411,6 +399,7 @@ int CCallback::getMyColor()
 }
 int CCallback::getHeroSerial(const CGHeroInstance * hero)
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	for (int i=0; i<gs->players[player].heroes.size();i++)
 	{
 		if (gs->players[player].heroes[i]==hero)
@@ -432,9 +421,6 @@ const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj)
 int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
 {
 	if(s1->tempOwner != player   ||   s2->tempOwner != player)
-
-
-
 		return -1;
 
 	*cl->serv << ui16(502) << ui8(1) << s1->id << ui8(p1) << s2->id << ui8(p2);
@@ -469,6 +455,7 @@ bool CCallback::dismissHero(const CGHeroInstance *hero)
 
 int CCallback::getMySerial()
 {	
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	return gs->players[player].serial;
 }
 
@@ -517,7 +504,8 @@ bool CCallback::buildBuilding(const CGTownInstance *town, si32 buildingID)
 
 int CCallback::battleGetBattlefieldType()
 {
-	return CGI->mh->ttiles[CGI->state->curB->tile.x][CGI->state->curB->tile.y][CGI->state->curB->tile.z].tileInfo->tertype;
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	return CGI->mh->ttiles[gs->curB->tile.x][gs->curB->tile.y][gs->curB->tile.z].tileInfo->tertype;
 }
 
 int CCallback::battleGetObstaclesAtTile(int tile) //returns bitfield 
@@ -527,17 +515,15 @@ int CCallback::battleGetObstaclesAtTile(int tile) //returns bitfield
 }
 int CCallback::battleGetStack(int pos)
 {
-	return CGI->state->battleGetStack(pos);
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	return gs->battleGetStack(pos);
 }
 
 CStack* CCallback::battleGetStackByID(int ID)
 {
-	for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
-	{
-		if(CGI->state->curB->stacks[g]->ID == ID)
-			return CGI->state->curB->stacks[g];
-	}
-	return NULL;
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	if(!gs->curB) return NULL;
+	return gs->curB->getStack(ID);
 }
 
 CStack* CCallback::battleGetStackByPos(int pos)
@@ -547,30 +533,33 @@ CStack* CCallback::battleGetStackByPos(int pos)
 
 int CCallback::battleGetPos(int stack)
 {
-	for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	for(int g=0; g<gs->curB->stacks.size(); ++g)
 	{
-		if(CGI->state->curB->stacks[g]->ID == stack)
-			return CGI->state->curB->stacks[g]->position;
+		if(gs->curB->stacks[g]->ID == stack)
+			return gs->curB->stacks[g]->position;
 	}
 	return -1;
 }
 
 std::map<int, CStack> CCallback::battleGetStacks()
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	std::map<int, CStack> ret;
-	for(int g=0; g<CGI->state->curB->stacks.size(); ++g)
+	for(int g=0; g<gs->curB->stacks.size(); ++g)
 	{
-		ret[CGI->state->curB->stacks[g]->ID] = *(CGI->state->curB->stacks[g]);
+		ret[gs->curB->stacks[g]->ID] = *(gs->curB->stacks[g]);
 	}
 	return ret;
 }
 
 CCreature CCallback::battleGetCreature(int number)
 {
-	for(int h=0; h<CGI->state->curB->stacks.size(); ++h)
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	for(int h=0; h<gs->curB->stacks.size(); ++h)
 	{
-		if(CGI->state->curB->stacks[h]->ID == number) //creature found
-			return *(CGI->state->curB->stacks[h]->creature);
+		if(gs->curB->stacks[h]->ID == number) //creature found
+			return *(gs->curB->stacks[h]->creature);
 	}
 #ifndef __GNUC__
 	throw new std::exception("Cannot find the creature");
@@ -581,20 +570,23 @@ CCreature CCallback::battleGetCreature(int number)
 
 std::vector<int> CCallback::battleGetAvailableHexes(int ID)
 {
-	return CGI->state->battleGetRange(ID);
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	return gs->battleGetRange(ID);
 }
 
 bool CCallback::battleIsStackMine(int ID)
 {
-	for(int h=0; h<CGI->state->curB->stacks.size(); ++h)
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
+	for(int h=0; h<gs->curB->stacks.size(); ++h)
 	{
-		if(CGI->state->curB->stacks[h]->ID == ID) //creature found
-			return CGI->state->curB->stacks[h]->owner == player;
+		if(gs->curB->stacks[h]->ID == ID) //creature found
+			return gs->curB->stacks[h]->owner == player;
 	}
 	return false;
 }
 bool CCallback::battleCanShoot(int ID, int dest) //TODO: finish
 {
+	boost::shared_lock<boost::shared_mutex> lock(*gs->mx);
 	if(battleGetStackByID(ID)->creature->isShooting() 
 		&& battleGetStack(dest) != -1 
 		&& battleGetStackByPos(dest)->owner != battleGetStackByID(ID)->owner

+ 141 - 248
CGameState.cpp

@@ -86,6 +86,140 @@ CGObjectInstance * createObject(int id, int subid, int3 pos, int owner)
 	//}
 	return nobj;
 }
+CStack * BattleInfo::getStack(int stackID)
+{
+	for(int g=0; g<stacks.size(); ++g)
+	{
+		if(stacks[g]->ID == stackID)
+			return stacks[g];
+	}
+	return NULL;
+}
+CStack * BattleInfo::getStackT(int tileID)
+{
+	for(int g=0; g<stacks.size(); ++g)
+	{
+		if(stacks[g]->position == tileID 
+			|| (stacks[g]->creature->isDoubleWide() && stacks[g]->attackerOwned && stacks[g]->position-1 == tileID)
+			|| (stacks[g]->creature->isDoubleWide() && !stacks[g]->attackerOwned && stacks[g]->position+1 == tileID))
+		{
+			if(stacks[g]->alive)
+			{
+				return stacks[g];
+			}
+		}
+	}
+	return NULL;
+}
+void BattleInfo::getAccessibilityMap(bool *accessibility)
+{
+	memset(accessibility,1,187); //initialize array with trues
+	for(int g=0; g<stacks.size(); ++g)
+	{
+		if(!stacks[g]->alive) //we don't want to lock enemy's positions and this units' position
+			continue;
+
+		accessibility[stacks[g]->position] = false;
+		if(stacks[g]->creature->isDoubleWide()) //if it's a double hex creature
+		{
+			if(stacks[g]->attackerOwned)
+				accessibility[stacks[g]->position-1] = false;
+			else
+				accessibility[stacks[g]->position+1] = false;
+		}
+	}
+}
+void BattleInfo::getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide) //send pointer to at least 187 allocated bytes
+{	
+	bool mac[187];
+	getAccessibilityMap(mac);
+	memcpy(accessibility,mac,187);
+
+	for(int b=0; b<187; ++b)
+	{
+		if( mac[b] && !(atackerSide ? mac[b-1] : mac[b+1]))
+		{
+			accessibility[b] = false;
+		}
+	}
+	//removing accessibility for side hexes
+	for(int v=0; v<187; ++v)
+		if(atackerSide ? (v%17)==1 : (v%17)==15)
+			accessibility[v] = false;
+}
+
+std::vector<int> BattleInfo::getPath(int start, int dest, bool*accessibility)
+{							
+	int predecessor[187]; //for getting the Path
+	for(int b=0; b<187; ++b)
+		predecessor[b] = -1;
+	//bfsing
+	int dists[187]; //calculated distances
+	std::queue<int> hexq; //bfs queue
+	hexq.push(start);
+	for(int g=0; g<187; ++g)
+		dists[g] = 100000000;
+	dists[hexq.front()] = 0;
+	int curNext = -1; //for bfs loop only (helper var)
+	while(!hexq.empty()) //bfs loop
+	{
+		int curHex = hexq.front();
+		hexq.pop();
+		curNext = curHex - ( (curHex/17)%2 ? 18 : 17 );
+		if((curNext > 0) && (accessibility[curNext] || curNext==dest) && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top left
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+			predecessor[curNext] = curHex;
+		}
+		curNext = curHex - ( (curHex/17)%2 ? 17 : 16 );
+		if((curNext > 0) && (accessibility[curNext] || curNext==dest)  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //top right
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+			predecessor[curNext] = curHex;
+		}
+		curNext = curHex - 1;
+		if((curNext > 0) && (accessibility[curNext] || curNext==dest)  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //left
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+			predecessor[curNext] = curHex;
+		}
+		curNext = curHex + 1;
+		if((curNext < 187) && (accessibility[curNext] || curNext==dest)  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //right
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+			predecessor[curNext] = curHex;
+		}
+		curNext = curHex + ( (curHex/17)%2 ? 16 : 17 );
+		if((curNext < 187) && (accessibility[curNext] || curNext==dest)  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom left
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+			predecessor[curNext] = curHex;
+		}
+		curNext = curHex + ( (curHex/17)%2 ? 17 : 18 );
+		if((curNext < 187) && (accessibility[curNext] || curNext==dest)  && (dists[curHex] + 1 < dists[curNext]) && (curNext)%17!=0 && (curNext)%17!=16) //bottom right
+		{
+			hexq.push(curNext);
+			dists[curNext] = dists[curHex] + 1;
+			predecessor[curNext] = curHex;
+		}
+	}
+
+	//following the Path
+	std::vector<int> path;
+	int curElem = dest;
+	while(curElem != start)
+	{
+		path.push_back(curElem);
+		curElem = predecessor[curElem];
+	}
+	return path;
+}
+
 CStack::CStack(CCreature * C, int A, int O, int I, bool AO)
 	:creature(C),amount(A),owner(O), alive(true), position(-1), ID(I), attackerOwned(AO), firstHPleft(C->hitPoints)
 {
@@ -238,6 +372,13 @@ void CGameState::apply(IPack * pack)
 				delete curB->stacks[i];
 			delete curB;
 			curB = NULL;
+			break;
+		}
+	case 3004:
+		{
+			BattleStackMoved *br = static_cast<BattleStackMoved*>(pack);
+			curB->getStack(br->stack)->position = br->tile;
+			break;
 		}
 	//case 1002://set hover name
 	//	{
@@ -749,254 +890,6 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 		}
 	}
 }
-void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2)
-{/*
-	curB = new BattleInfo();
-	std::vector<CStack*> & stacks = (curB->stacks);
-
-	curB->army1=army1;
-	curB->army2=army2;
-	curB->hero1=dynamic_cast<CGHeroInstance*>(hero1);
-	curB->hero2=dynamic_cast<CGHeroInstance*>(hero2);
-	curB->side1=(hero1)?(hero1->tempOwner):(-1);
-	curB->side2=(hero2)?(hero2->tempOwner):(-1);
-	curB->round = -2;
-	curB->stackActionPerformed = false;
-	for(std::map<int,std::pair<ui32,si32> >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++)
-	{
-		stacks.push_back(new CStack(i->second.first,i->second.second,0, stacks.size(), true));
-		stacks[stacks.size()-1]->ID = stacks.size()-1;
-	}
-	//initialization of positions
-	switch(army1->slots.size()) //for attacker
-	{
-	case 0:
-		break;
-	case 1:
-		stacks[0]->position = 86; //6
-		break;
-	case 2:
-		stacks[0]->position = 35; //3
-		stacks[1]->position = 137; //9
-		break;
-	case 3:
-		stacks[0]->position = 35; //3
-		stacks[1]->position = 86; //6
-		stacks[2]->position = 137; //9
-		break;
-	case 4:
-		stacks[0]->position = 1; //1
-		stacks[1]->position = 69; //5
-		stacks[2]->position = 103; //7
-		stacks[3]->position = 171; //11
-		break;
-	case 5:
-		stacks[0]->position = 1; //1
-		stacks[1]->position = 35; //3
-		stacks[2]->position = 86; //6
-		stacks[3]->position = 137; //9
-		stacks[4]->position = 171; //11
-		break;
-	case 6:
-		stacks[0]->position = 1; //1
-		stacks[1]->position = 35; //3
-		stacks[2]->position = 69; //5
-		stacks[3]->position = 103; //7
-		stacks[4]->position = 137; //9
-		stacks[5]->position = 171; //11
-		break;
-	case 7:
-		stacks[0]->position = 1; //1
-		stacks[1]->position = 35; //3
-		stacks[2]->position = 69; //5
-		stacks[3]->position = 86; //6
-		stacks[4]->position = 103; //7
-		stacks[5]->position = 137; //9
-		stacks[6]->position = 171; //11
-		break;
-	default: //fault
-		break;
-	}
-	for(std::map<int,std::pair<ui32,si32> >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++)
-		stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size(), false));
-	switch(army2->slots.size()) //for defender
-	{
-	case 0:
-		break;
-	case 1:
-		stacks[0+army1->slots.size()]->position = 100; //6
-		break;
-	case 2:
-		stacks[0+army1->slots.size()]->position = 49; //3
-		stacks[1+army1->slots.size()]->position = 151; //9
-		break;
-	case 3:
-		stacks[0+army1->slots.size()]->position = 49; //3
-		stacks[1+army1->slots.size()]->position = 100; //6
-		stacks[2+army1->slots.size()]->position = 151; //9
-		break;
-	case 4:
-		stacks[0+army1->slots.size()]->position = 15; //1
-		stacks[1+army1->slots.size()]->position = 83; //5
-		stacks[2+army1->slots.size()]->position = 117; //7
-		stacks[3+army1->slots.size()]->position = 185; //11
-		break;
-	case 5:
-		stacks[0+army1->slots.size()]->position = 15; //1
-		stacks[1+army1->slots.size()]->position = 49; //3
-		stacks[2+army1->slots.size()]->position = 100; //6
-		stacks[3+army1->slots.size()]->position = 151; //9
-		stacks[4+army1->slots.size()]->position = 185; //11
-		break;
-	case 6:
-		stacks[0+army1->slots.size()]->position = 15; //1
-		stacks[1+army1->slots.size()]->position = 49; //3
-		stacks[2+army1->slots.size()]->position = 83; //5
-		stacks[3+army1->slots.size()]->position = 117; //7
-		stacks[4+army1->slots.size()]->position = 151; //9
-		stacks[5+army1->slots.size()]->position = 185; //11
-		break;
-	case 7:
-		stacks[0+army1->slots.size()]->position = 15; //1
-		stacks[1+army1->slots.size()]->position = 49; //3
-		stacks[2+army1->slots.size()]->position = 83; //5
-		stacks[3+army1->slots.size()]->position = 100; //6
-		stacks[4+army1->slots.size()]->position = 117; //7
-		stacks[5+army1->slots.size()]->position = 151; //9
-		stacks[6+army1->slots.size()]->position = 185; //11
-		break;
-	default: //fault
-		break;
-	}
-	for(int g=0; g<stacks.size(); ++g) //shifting positions of two-hex creatures
-	{
-		if((stacks[g]->position%17)==1 && stacks[g]->creature->isDoubleWide())
-		{
-			stacks[g]->position += 1;
-		}
-		else if((stacks[g]->position%17)==15 && stacks[g]->creature->isDoubleWide())
-		{
-			stacks[g]->position -= 1;
-		}
-	}
-	std::stable_sort(stacks.begin(),stacks.end(),cmpst);
-
-	//for start inform players about battle
-	for(std::map<int, PlayerState>::iterator j=players.begin(); j!=players.end(); ++j)//->players.size(); ++j) //for testing
-	{
-		if (j->first > PLAYER_LIMIT)
-			break;
-		if(j->second.fogOfWarMap[tile.x][tile.y][tile.z])
-		{ //player should be notified
-			tribool side = tribool::indeterminate_value;
-			if(j->first == curB->side1) //player is attacker
-				side = false;
-			else if(j->first == curB->side2) //player is defender
-				side = true;
-			else 
-				continue; //no witnesses
-			if(VLC->playerint[j->second.serial]->human)
-			{
-				((CPlayerInterface*)( VLC->playerint[j->second.serial] ))->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side);
-			}
-			else
-			{
-				//VLC->playerint[j->second.serial]->battleStart(army1, army2, tile, curB->hero1, curB->hero2, side);
-			}
-		}
-	}
-
-	curB->round++;
-	if( (curB->hero1 && curB->hero1->getSecSkillLevel(19)>=0) || ( curB->hero2 && curB->hero2->getSecSkillLevel(19)>=0)  )//someone has tactics
-	{
-		//TODO: wywolania dla rundy -1, ograniczenie pola ruchu, etc
-	}
-
-	curB->round++;
-
-	//SDL_Thread * eventh = SDL_CreateThread(battleEventThread, NULL);
-
-	while(true) //till the end of the battle ;]
-	{
-		bool battleEnd = false;
-		//tell players about next round
-		for(int v=0; v<VLC->playerint.size(); ++v)
-			VLC->playerint[v]->battleNewRound(curB->round);
-
-		//stack loop
-		for(int i=0;i<stacks.size();i++)
-		{
-			curB->activeStack = i;
-			curB->stackActionPerformed = false;
-			if(stacks[i]->alive) //indicate posiibility of making action for this unit
-			{
-				unsigned char owner = (stacks[i]->owner)?(hero2 ? hero2->tempOwner : 255):(hero1->tempOwner);
-				unsigned char serialOwner = -1;
-				for(int g=0; g<VLC->playerint.size(); ++g)
-				{
-					if(VLC->playerint[g]->playerID == owner)
-					{
-						serialOwner = g;
-						break;
-					}
-				}
-				if(serialOwner==255) //neutral unit
-				{
-				}
-				else if(VLC->playerint[serialOwner]->human)
-				{
-					BattleAction ba = ((CPlayerInterface*)VLC->playerint[serialOwner])->activeStack(stacks[i]->ID);
-					switch(ba.actionType)
-					{
-					case 2: //walk
-						{
-							battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
-						}
-					case 3: //defend
-						{
-							break;
-						}
-					case 4: //retreat/flee
-						{
-							for(int v=0; v<VLC->playerint.size(); ++v) //tell about the end of this battle to interfaces
-								VLC->playerint[v]->battleEnd(army1, army2, hero1, hero2, std::vector<int>(), 0, false);
-							battleEnd = true;
-							break;
-						}
-					case 6: //walk or attack
-						{
-							battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
-							battleAttackCreatureStack(ba.stackNumber, ba.destinationTile);
-							break;
-						}
-					case 7: //shoot
-						{
-							battleShootCreatureStack(ba.stackNumber, ba.destinationTile);
-							break;
-						}
-					}
-				}
-				else
-				{
-					//VLC->playerint[serialOwner]->activeStack(stacks[i]->ID);
-				}
-			}
-			if(battleEnd)
-				break;
-			//sprawdzic czy po tej akcji ktoras strona nie wygrala bitwy
-		}
-		if(battleEnd)
-			break;
-		curB->round++;
-		SDL_Delay(50);
-	}
-
-	for(int i=0;i<stacks.size();i++)
-		delete stacks[i];
-	delete curB;
-	curB = NULL;*/
-}
-
 bool CGameState::battleMoveCreatureStack(int ID, int dest)
 {/*
 	//first checks

+ 7 - 1
CGameState.h

@@ -1,8 +1,10 @@
 #ifndef CGAMESTATE_H
 #define CGAMESTATE_H
 #include "global.h"
+#ifndef _MSC_VER
 #include "../hch/CCreatureHandler.h"
 #include "lib/VCMI_Lib.h"
+#endif
 #include <set>
 #include <vector>
 #ifdef _WIN32
@@ -61,6 +63,11 @@ struct DLL_EXPORT BattleInfo
 	{
 		h & side1 & side2 & round & activeStack & siege & tile & stacks & army1 & army2 & hero1 & hero2;
 	}
+	CStack * getStack(int stackID);
+	CStack * getStackT(int tileID);
+	void getAccessibilityMap(bool *accessibility); //send pointer to at least 187 allocated bytes
+	void getAccessibilityMapForTwoHex(bool *accessibility, bool atackerSide); //send pointer to at least 187 allocated bytes
+	std::vector<int> getPath(int start, int dest, bool*accessibility);
 };
 
 class DLL_EXPORT CStack
@@ -122,7 +129,6 @@ private:
 
 	CGHeroInstance *getHero(int objid);
 
-	void battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, CArmedInstance *hero1, CArmedInstance *hero2);
 	bool battleMoveCreatureStack(int ID, int dest);
 	bool battleAttackCreatureStack(int ID, int dest);
 	bool battleShootCreatureStack(int ID, int dest);

+ 2 - 0
CPlayerInterface.cpp

@@ -1993,6 +1993,7 @@ BattleAction CPlayerInterface::activeStack(int stackID) //called when it's turn
 	//tidy up
 	BattleAction ret = *(b->givenCommand->data);
 	delete b->givenCommand->data;
+	b->givenCommand->data = NULL;
 
 	//return command
 	return ret;
@@ -2010,6 +2011,7 @@ void CPlayerInterface::battleEnd(BattleResult *br)
 
 void CPlayerInterface::battleStackMoved(int ID, int dest, bool startMoving, bool endMoving)
 {
+	boost::unique_lock<boost::mutex> un(*pim);
 	dynamic_cast<CBattleInterface*>(curint)->stackMoved(ID, dest, startMoving, endMoving);
 }
 

+ 13 - 3
client/Client.cpp

@@ -353,7 +353,7 @@ void CClient::process(int what)
 			*serv >> sas;
 			std::cout << "Active stack: " << sas.stack <<std::endl;
 			gs->apply(&sas);
-			boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,gs->curB->stacks[sas.stack]->owner));
+			boost::thread(boost::bind(&CClient::waitForMoveAndSend,this,gs->curB->getStack(sas.stack)->owner));
 			break;
 		}
 	case 3003:
@@ -368,8 +368,18 @@ void CClient::process(int what)
 				playerint[gs->curB->side2]->battleEnd(&br);
 
 			gs->apply(&br);
-
-
+			break;
+		}
+	case 3004:
+		{
+			BattleStackMoved br;
+			*serv >> br;
+			std::cout << "Stack "<<br.stack <<" moves to the tile "<<br.tile<<std::endl;
+			if(playerint.find(gs->curB->side1) != playerint.end())
+				playerint[gs->curB->side1]->battleStackMoved(br.stack,br.tile,br.flags&1,br.flags&2);
+			if(playerint.find(gs->curB->side2) != playerint.end())
+				playerint[gs->curB->side2]->battleStackMoved(br.stack,br.tile,br.flags&1,br.flags&2);
+			gs->apply(&br);
 			break;
 		}
 	case 9999:

+ 22 - 0
lib/NetPacks.h

@@ -301,6 +301,28 @@ struct BattleResult : public CPack<BattleResult>//3003
 	}
 };
 
+struct BattleStackMoved : public CPack<BattleStackMoved>//3004
+{
+	ui32 stack, tile;
+	ui8 flags;
+
+
+
+	BattleStackMoved(){flags = 0; type = 3004;};
+	bool startMoving()
+	{
+		return flags & 1;
+	}
+	bool endMoving()
+	{
+		return flags & 2;
+	}
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & stack & tile & flags;
+	}
+};
+
 struct ShowInInfobox : public CPack<ShowInInfobox> //107
 {
 	ShowInInfobox(){type = 107;};

+ 1 - 1
lib/VCMI_Lib.h

@@ -57,7 +57,7 @@ public:
 	//StartInfo scenarioOps;
 };
 
-#ifndef __GNUC__
+#ifdef __GNUC__
 DLL_EXPORT LibClasses * VLC;
 #else
 extern DLL_EXPORT LibClasses * VLC;

+ 76 - 2
server/CGameHandler.cpp

@@ -315,7 +315,7 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
 		{
 			if(!stacks[i]->alive) continue;//indicates imposiibility of making action for this dead unit
 			BattleSetActiveStack sas;
-			sas.stack = i;
+			sas.stack = stacks[i]->ID;
 			sendAndApply(&sas);
 
 			//wait for response about battle action
@@ -323,6 +323,7 @@ void CGameHandler::startBattle(CCreatureSet army1, CCreatureSet army2, int3 tile
 			boost::unique_lock<boost::mutex> lock(battleMadeAction.mx);
 			while(!battleMadeAction.data)
 				battleMadeAction.cond.wait(lock);
+			battleMadeAction.data = false;
 		}
 	}
 
@@ -584,7 +585,80 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					{
 					case 2: //walk
 						{
-							//battleMoveCreatureStack(ba.stackNumber, ba.destinationTile);
+							CStack *curStack = gs->curB->getStack(ba.stackNumber),
+								*stackAtEnd = gs->curB->getStackT(ba.destinationTile);
+
+							//initing necessary tables
+							bool accessibility[187];
+							if(curStack->creature->isDoubleWide())
+							{
+								gs->curB->getAccessibilityMapForTwoHex(accessibility,curStack->attackerOwned);
+								accessibility[curStack->attackerOwned ? curStack->position+1 : curStack->position-1]=true;//OUR second tile is for US accessible
+							}
+							else 
+								gs->curB->getAccessibilityMap(accessibility);
+							accessibility[curStack->position] = true; //OUR tile is for US accessible
+
+							//if(!stackAtEnd && !accessibility[dest])
+							//	return false;
+
+							//if(dists[dest] > curStack->creature->speed && !(stackAtEnd && dists[dest] == curStack->creature->speed+1)) //we can attack a stack if we can go to adjacent hex
+							//	return false;
+
+							std::vector<int> path = gs->curB->getPath(curStack->position,ba.destinationTile,accessibility);
+
+							for(int v=path.size()-1; v>=0; --v)
+							{
+								if(v!=0 || !stackAtEnd) //it's not the last step or the last tile is free
+								{
+									//inform clients about move
+									BattleStackMoved sm;
+									sm.stack = curStack->ID;
+									sm.tile = path[v];
+									if(v==path.size()-1)//move start - set flag
+										sm.flags |= 1;
+									if(v==0 || (stackAtEnd && v==1)) //move end - set flag
+										sm.flags |= 2;
+									sendAndApply(&sm);
+								}
+								else //if it's last step and we should attack unit at the end
+								{
+									//LOCPLINT->battleStackAttacking(ID, path[v]);
+									////counting dealt damage
+									//int finalDmg = calculateDmg(curStack, curB->stacks[numberOfStackAtEnd]);
+
+									////applying damages
+									//int cresKilled = finalDmg / curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
+									//int damageFirst = finalDmg % curB->stacks[numberOfStackAtEnd]->creature->hitPoints;
+
+									//if( curB->stacks[numberOfStackAtEnd]->firstHPleft <= damageFirst )
+									//{
+									//	curB->stacks[numberOfStackAtEnd]->amount -= 1;
+									//	curB->stacks[numberOfStackAtEnd]->firstHPleft += curB->stacks[numberOfStackAtEnd]->creature->hitPoints - damageFirst;
+									//}
+									//else
+									//{
+									//	curB->stacks[numberOfStackAtEnd]->firstHPleft -= damageFirst;
+									//}
+
+									//int cresInstackBefore = curB->stacks[numberOfStackAtEnd]->amount; 
+									//curB->stacks[numberOfStackAtEnd]->amount -= cresKilled;
+									//if(curB->stacks[numberOfStackAtEnd]->amount<=0) //stack killed
+									//{
+									//	curB->stacks[numberOfStackAtEnd]->amount = 0;
+									//	LOCPLINT->battleStackKilled(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore) , ID, false);
+									//	curB->stacks[numberOfStackAtEnd]->alive = false;
+									//}
+									//else
+									//{
+									//	LOCPLINT->battleStackIsAttacked(curB->stacks[numberOfStackAtEnd]->ID, finalDmg, std::min(cresKilled, cresInstackBefore), ID, false);
+									//}
+
+									//damage applied
+								}
+							}
+							//curB->stackActionPerformed = true;
+							//LOCPLINT->actionFinished(BattleAction());
 							break;
 						}
 					case 3: //defend

+ 2 - 0
server/CGameHandler.h

@@ -3,7 +3,9 @@
 #include <set>
 #include "../CGameState.h"
 #include "../lib/Connection.h"
+#ifndef _MSC_VER
 #include <boost/thread.hpp>
+#endif
 class CVCMIServer;
 class CGameState;
 //class CConnection;