Browse Source

Made CreatureSet serializable and using creature id. Stack moving, swapping, merging, splitting.

Michał W. Urbańczyk 17 years ago
parent
commit
5c5c80933b
15 changed files with 235 additions and 170 deletions
  1. 10 60
      CCallback.cpp
  2. 10 3
      CGameState.cpp
  3. 1 1
      CLua.cpp
  4. 4 4
      CPlayerInterface.cpp
  5. 12 0
      client/Client.cpp
  6. 4 4
      client/Graphics.cpp
  7. 9 3
      client/VCMI_client.vcproj
  8. 2 2
      hch/CObjectHandler.cpp
  9. 6 2
      int3.h
  10. 19 0
      lib/Connection.h
  11. 10 0
      lib/NetPacks.h
  12. 11 81
      lib/VCMI_lib.vcproj
  13. 8 7
      map.cpp
  14. 52 3
      server/CGameHandler.cpp
  15. 77 0
      server/VCMI_server.vcproj

+ 10 - 60
CCallback.cpp

@@ -136,11 +136,11 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount
 
 		//recruit
 		int slot = -1; //slot ID
-		std::pair<int,std::pair<CCreature*,int> > parb;	
+		std::pair<si32,std::pair<ui32,si32> > parb;	
 
 		for(int i=0;i<7;i++) //TODO: if there is already stack of same creatures it should be used always
 		{
-			if((!t->army.slots[i].first) || (t->army.slots[i].first->idNumber == ID)) //slot is free or there is saem creature
+			if(((!t->army.slots[i].first) && (!t->army.slots[i].second)) || (t->army.slots[i].first == ID)) //slot is free or there is saem creature
 			{
 				slot = i;
 				break;
@@ -160,7 +160,7 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount
 		}
 		else //create new stack in the garrison
 		{
-			t->army.slots[slot].first = &CGI->creh->creatures[ID];
+			t->army.slots[slot].first = ID;
 			t->army.slots[slot].second = amount;
 		}
 		cl->playerint[player]->garrisonChanged(obj);
@@ -194,7 +194,7 @@ void CCallback::endTurn()
 UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
 {
 	UpgradeInfo ret;
-	CCreature *base = ((CArmedInstance*)obj)->army.slots[stackPos].first;
+	CCreature *base = &CGI->creh->creatures[((CArmedInstance *)obj)->army.slots[stackPos].first];
 	if((obj->ID == 98)  ||  ((obj->ID == 34) && static_cast<const CGHeroInstance*>(obj)->visitedTown))
 	{
 		CGTownInstance * t;
@@ -404,79 +404,29 @@ const CCreatureSet* CCallback::getGarrison(const CGObjectInstance *obj)
 
 int CCallback::swapCreatures(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
 {
-	CCreatureSet *S1 = const_cast<CCreatureSet*>(getGarrison(s1)), *S2 = const_cast<CCreatureSet*>(getGarrison(s2));
-	if (false)
-	{
-		//TODO: check if we are allowed to swap these creatures
+	if(s1->tempOwner != player   ||   s2->tempOwner != player)
 		return -1;
-	}
 
-	CCreature * pom = S2->slots[p2].first;
-	S2->slots[p2].first = S1->slots[p1].first;
-	S1->slots[p1].first = pom;
-	int pom2 = S2->slots[p2].second;
-	S2->slots[p2].second = S1->slots[p1].second;
-	S1->slots[p1].second = pom2;
-
-	if(!S1->slots[p1].first)
-		S1->slots.erase(p1);
-	if(!S2->slots[p2].first)
-		S2->slots.erase(p2);
-
-	if(s1->tempOwner<PLAYER_LIMIT)
-		cl->playerint[s1->tempOwner]->garrisonChanged(s1);
-	if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1))
-		cl->playerint[s2->tempOwner]->garrisonChanged(s2);
+	*cl->serv << ui16(502) << ui8(1) << s1->id << ui8(p1) << s2->id << ui8(p2);
 	return 0;
 }
 
 int CCallback::mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
 {	
-	CCreatureSet *S1 = const_cast<CCreatureSet*>(getGarrison(s1)), *S2 = const_cast<CCreatureSet*>(getGarrison(s2));
-	if ((S1->slots[p1].first != S2->slots[p2].first) && (true /*we are allowed to*/))
+	if ((s1->tempOwner!= player  ||  s2->tempOwner!=player))
 	{
 		return -1;
 	}
-
-
-	S2->slots[p2].second += S1->slots[p1].second;
-	S1->slots[p1].first = NULL;
-	S1->slots[p1].second = 0;
-
-	S1->slots.erase(p1);
-
-	if(s1->tempOwner<PLAYER_LIMIT)
-		cl->playerint[s1->tempOwner]->garrisonChanged(s1);
-
-	if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1))
-		cl->playerint[s2->tempOwner]->garrisonChanged(s2);
+	*cl->serv << ui16(502) << ui8(2) << s1->id << ui8(p1) << s2->id << ui8(p2);
 	return 0;
 }
 int CCallback::splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val)
 {
-	if(!val)
-		return -1;
-	CCreatureSet *S1 = const_cast<CCreatureSet*>(getGarrison(s1)), *S2 = const_cast<CCreatureSet*>(getGarrison(s2));
-	if ((S1->slots[p1].second<val) && (true /*we are allowed to*/))
+	if (s1->tempOwner!= player  ||  s2->tempOwner!=player || (!val))
 	{
 		return -1;
 	}
-
-	S2->slots[p2].first = S1->slots[p1].first;
-	S2->slots[p2].second = val;
-	S1->slots[p1].second -= val;
-	if(!S1->slots[p1].second) //if we've moved all creatures
-		S1->slots.erase(p1); 
-
-
-	if(s1->tempOwner<PLAYER_LIMIT)
-	{
-		cl->playerint[s1->tempOwner]->garrisonChanged(s1);
-	}
-	if((s2->tempOwner<PLAYER_LIMIT) && (s2 != s1))
-	{
-		cl->playerint[s2->tempOwner]->garrisonChanged(s2);
-	}
+	*cl->serv << ui16(502) << ui8(3) << s1->id << ui8(p1) << s2->id << ui8(p2) << si32(val);
 	return 0;
 }
 

+ 10 - 3
CGameState.cpp

@@ -141,6 +141,13 @@ void CGameState::apply(IPack * pack)
 				players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1;
 			break;
 		}
+	case 502:
+		{
+			SetGarrisons * n = static_cast<SetGarrisons*>(pack);
+			for(std::map<ui32,CCreatureSet>::iterator i = n->garrs.begin(); i!=n->garrs.end(); i++)
+				static_cast<CArmedInstance*>(map->objects[i->first])->army = i->second;
+			break;
+		}
 	case 1001://set object property
 		{
 			SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
@@ -568,7 +575,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 					}
 					continue;
 				}
-				vhi->army.slots[x-pom2].first = &(VLC->creh->creatures[pom]);
+				vhi->army.slots[x-pom2].first = pom;
 				if((pom = (vhi->type->highStack[x]-vhi->type->lowStack[x])) > 0)
 					vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x];
 				else 
@@ -674,7 +681,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 	curB->side2=(hero2)?(hero2->tempOwner):(-1);
 	curB->round = -2;
 	curB->stackActionPerformed = false;
-	for(std::map<int,std::pair<CCreature*,int> >::iterator i = army1->slots.begin(); i!=army1->slots.end(); i++)
+	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;
@@ -729,7 +736,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 	default: //fault
 		break;
 	}
-	for(std::map<int,std::pair<CCreature*,int> >::iterator i = army2->slots.begin(); i!=army2->slots.end(); i++)
+	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
 	{

+ 1 - 1
CLua.cpp

@@ -720,7 +720,7 @@ void CMonsterS::onHeroVisit(int objid, int heroID)
 	DEFOS;
 	CCreatureSet set;
 	//TODO: zrobic secik w sposob wyrafinowany
-	set.slots[0] = std::pair<CCreature*,int>(&VLC->creh->creatures[os->subID],((CCreatureObjInfo*)os->info)->number);
+	set.slots[0] = std::pair<ui32,si32>(os->subID,((CCreatureObjInfo*)os->info)->number);
 	cb->startBattle(heroID,&set,os->pos);
 }
 std::vector<int> CMonsterS::yourObjects() //returns IDs of objects which are handled by script

+ 4 - 4
CPlayerInterface.cpp

@@ -342,11 +342,11 @@ void CGarrisonInt::createSlots()
 	{
 		sup = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL));
 		for
-			(std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=set1->slots.begin();
+			(std::map<si32,std::pair<ui32,si32> >::const_iterator i=set1->slots.begin();
 			i!=set1->slots.end(); i++)
 		{
 			(*sup)[i->first] = 
-				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y,i->first, 0, i->second.first,i->second.second);
+				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y,i->first, 0, &CGI->creh->creatures[i->second.first],i->second.second);
 		}
 		for(int i=0; i<sup->size(); i++)
 			if((*sup)[i] == NULL)
@@ -356,11 +356,11 @@ void CGarrisonInt::createSlots()
 	{	
 		sdown = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL));
 		for
-			(std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=set2->slots.begin();
+			(std::map<si32,std::pair<ui32,si32> >::const_iterator i=set2->slots.begin();
 			i!=set2->slots.end(); i++)
 		{
 			(*sdown)[i->first] = 
-				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first,1, i->second.first,i->second.second);
+				new CGarrisonSlot(this, pos.x + (i->first*(58+interx)), pos.y + 64 + intery,i->first,1, &CGI->creh->creatures[i->second.first],i->second.second);
 		}
 		for(int i=0; i<sup->size(); i++)
 			if((*sdown)[i] == NULL)

+ 12 - 0
client/Client.cpp

@@ -114,7 +114,10 @@ CClient::CClient(CConnection *con, StartInfo *si)
 	std::cout << "\tOur checksum for the map: "<< mapa->checksum << std::endl;
 
 	if(mapa->checksum != sum)
+	{
+		throw std::exception("Wrong checksum");
 		exit(-1);
+	}
 	std::cout << "\tUsing random seed: "<<seed << std::endl;
 
 	gs = CGI->state;
@@ -223,6 +226,15 @@ void CClient::process(int what)
 			mess.cv->notify_all();
 			break;
 		}
+	case 502:
+		{
+			SetGarrisons sg;
+			*serv >> sg;
+			gs->apply(&sg);
+			for(std::map<ui32,CCreatureSet>::iterator i = sg.garrs.begin(); i!=sg.garrs.end(); i++)
+				playerint[gs->map->objects[i->first]->tempOwner]->garrisonChanged(gs->map->objects[i->first]);
+			break;
+		}
 	case 1001:
 		{
 			SetObjectProperty sop;

+ 4 - 4
client/Graphics.cpp

@@ -35,9 +35,9 @@ SDL_Surface * Graphics::drawHeroInfoWin(const CGHeroInstance * curh)
 	SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
 	printAt(curh->name,75,15,GEOR13,zwykly,ret);
 	drawPrimarySkill(curh, ret);
-	for (std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++)
+	for (std::map<si32,std::pair<ui32,si32> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++)
 	{
-		blitAt(graphics->smallImgs[(*i).second.first->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
+		blitAt(graphics->smallImgs[(*i).second.first],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
 		itoa((*i).second.second,buf,10);
 		printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+39,GEORM,zwykly,ret);
 	}
@@ -64,11 +64,11 @@ SDL_Surface * Graphics::drawTownInfoWin(const CGTownInstance * curh)
 		blitAt(halls->ourImages[pom].bitmap,77,42,ret);
 	itoa(curh->dailyIncome(),buf,10);
 	printAtMiddle(buf,167,70,GEORM,zwykly,ret);
-	for (std::map<si32,std::pair<CCreature*,si32> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++)
+	for (std::map<si32,std::pair<ui32,si32> >::const_iterator i=curh->army.slots.begin(); i!=curh->army.slots.end();i++)
 	{
 		if(!i->second.first)
 			continue;
-		blitAt(graphics->smallImgs[(*i).second.first->idNumber],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
+		blitAt(graphics->smallImgs[(*i).second.first],slotsPos[(*i).first].first+1,slotsPos[(*i).first].second+1,ret);
 		itoa((*i).second.second,buf,10);
 		printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+39,GEORM,zwykly,ret);
 	}

+ 9 - 3
client/VCMI_client.vcproj

@@ -171,7 +171,7 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Optibug|Win32"
+			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="1"
@@ -199,10 +199,14 @@
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
+				EnableFiberSafeOptimizations="true"
+				WholeProgramOptimization="true"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				StringPooling="true"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="false"
+				EnableEnhancedInstructionSet="0"
 				WarningLevel="3"
 				DebugInformationFormat="3"
 			/>
@@ -220,8 +224,10 @@
 				AdditionalDependencies="SDL.lib zdll.lib SDL_image.lib SDL_ttf.lib SDL_mixer.lib lua5.1.lib VCMI_lib.lib"
 				AdditionalLibraryDirectories="G:\vcmt\repa\libs"
 				GenerateDebugInformation="true"
+				Driver="0"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
+				LinkTimeCodeGeneration="0"
 				TargetMachine="1"
 			/>
 			<Tool

+ 2 - 2
hch/CObjectHandler.cpp

@@ -179,8 +179,8 @@ unsigned int CGHeroInstance::getLowestCreatureSpeed()
 	unsigned int sl = 100;
 	for(int h=0; h<army.slots.size(); ++h)
 	{
-		if(army.slots[h].first->speed<sl)
-			sl = army.slots[h].first->speed;
+		if(VLC->creh->creatures[army.slots[h].first].speed<sl)
+			sl = VLC->creh->creatures[army.slots[h].first].speed;
 	}
 	return sl;
 }

+ 6 - 2
int3.h

@@ -5,8 +5,12 @@ class CCreature;
 class CCreatureSet //seven combined creatures
 {
 public:
-	std::map<si32,std::pair<CCreature*,si32> > slots;
-	bool formation; //false - wide, true - tight
+	std::map<si32,std::pair<ui32,si32> > slots; //slots[slot_id]=> pair(creature_id,creature_quantity)
+	bool formation; //false - wide, true - tight	
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & slots & formation;
+	}
 };
 
 class int3

+ 19 - 0
lib/Connection.h

@@ -262,6 +262,25 @@ public:
 	{
 		*this >> data.first >> data.second;
 	}
+	template <typename T1, typename T2>
+	void saveSerializable(const std::map<T1,T2> &data)
+	{
+		*this << ui32(data.size());
+		for(std::map<T1,T2>::const_iterator i=data.begin();i!=data.end();i++)
+			*this << i->first << i->second;
+	}
+	template <typename T1, typename T2>
+	void loadSerializable(std::map<T1,T2> &data)
+	{
+		ui32 length;
+		*this >> length;
+		T1 t;
+		for(int i=0;i<length;i++)
+		{
+			*this >> t;
+			*this >> data[t];
+		}
+	}
 	template <typename T>
 	void save(const T &data)
 	{

+ 10 - 0
lib/NetPacks.h

@@ -85,6 +85,16 @@ struct TryMoveHero : public CPack<TryMoveHero> //501
 		h & id & result & start & end & movePoints & fowRevealed;
 	}
 }; 
+struct SetGarrisons : public CPack<SetGarrisons> //502
+{
+	SetGarrisons(){type = 502;};
+	std::map<ui32,CCreatureSet> garrs;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & garrs;
+	}
+}; 
 struct MetaString : public CPack<MetaString> //2001 helper for object scrips
 {
 	std::vector<std::string> strings;

+ 11 - 81
lib/VCMI_lib.vcproj

@@ -169,11 +169,11 @@
 			/>
 		</Configuration>
 		<Configuration
-			Name="Optibug_dll|Win32"
+			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
-			CharacterSet="2"
+			CharacterSet="1"
 			WholeProgramOptimization="1"
 			>
 			<Tool
@@ -193,18 +193,20 @@
 			/>
 			<Tool
 				Name="VCCLCompilerTool"
-				Optimization="0"
+				Optimization="3"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				EnableFiberSafeOptimizations="true"
+				WholeProgramOptimization="true"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				StringPooling="true"
 				MinimalRebuild="false"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="false"
 				WarningLevel="3"
-				DebugInformationFormat="4"
+				DebugInformationFormat="3"
 			/>
 			<Tool
 				Name="VCManagedResourceCompilerTool"
@@ -217,85 +219,13 @@
 			/>
 			<Tool
 				Name="VCLinkerTool"
-				AdditionalDependencies="SDL.lib zdll.lib SDL_image.lib SDL_ttf.lib"
-				Version="0.7"
+				AdditionalDependencies="zdll.lib"
+				Version=""
 				AdditionalLibraryDirectories="G:\vcmt\repa\libs"
 				GenerateDebugInformation="true"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
-				LinkTimeCodeGeneration="1"
-				TargetMachine="1"
-			/>
-			<Tool
-				Name="VCALinkTool"
-			/>
-			<Tool
-				Name="VCManifestTool"
-			/>
-			<Tool
-				Name="VCXDCMakeTool"
-			/>
-			<Tool
-				Name="VCBscMakeTool"
-			/>
-			<Tool
-				Name="VCFxCopTool"
-			/>
-			<Tool
-				Name="VCAppVerifierTool"
-			/>
-			<Tool
-				Name="VCPostBuildEventTool"
-			/>
-		</Configuration>
-		<Configuration
-			Name="Debugop|Win32"
-			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
-			IntermediateDirectory="$(ConfigurationName)"
-			ConfigurationType="2"
-			CharacterSet="2"
-			>
-			<Tool
-				Name="VCPreBuildEventTool"
-			/>
-			<Tool
-				Name="VCCustomBuildTool"
-			/>
-			<Tool
-				Name="VCXMLDataGeneratorTool"
-			/>
-			<Tool
-				Name="VCWebServiceProxyGeneratorTool"
-			/>
-			<Tool
-				Name="VCMIDLTool"
-			/>
-			<Tool
-				Name="VCCLCompilerTool"
-				Optimization="0"
-				AdditionalIncludeDirectories="G:\vcmt\repa\include"
-				MinimalRebuild="true"
-				BasicRuntimeChecks="0"
-				RuntimeLibrary="0"
-				WarningLevel="2"
-				SuppressStartupBanner="true"
-				DebugInformationFormat="0"
-				DisableSpecificWarnings="4251"
-			/>
-			<Tool
-				Name="VCManagedResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCResourceCompilerTool"
-			/>
-			<Tool
-				Name="VCPreLinkEventTool"
-			/>
-			<Tool
-				Name="VCLinkerTool"
-				AdditionalDependencies="SDL.lib zdll.lib SDL_image.lib SDL_ttf.lib"
-				AdditionalLibraryDirectories="G:\vcmt\repa\libs"
-				GenerateDebugInformation="true"
+				LinkTimeCodeGeneration="0"
 				TargetMachine="1"
 			/>
 			<Tool

+ 8 - 7
map.cpp

@@ -170,16 +170,16 @@ CCreatureSet readCreatureSet(unsigned char * bufor, int &i, int number, bool ver
 	if(version)
 	{
 		CCreatureSet ret;
-		std::pair<CCreature *, int> ins;
+		std::pair<ui32,si32> ins;
 		for(int ir=0;ir<number;ir++)
 		{
 			int rettt = readNormalNr(bufor,i+ir*4, 2);
 			if(rettt==0xffff) continue;
 			if(rettt>32768)
 				rettt = 65536-rettt+VLC->creh->creatures.size()-16;
-			ins.first = &(VLC->creh->creatures[rettt]);
+			ins.first = rettt;
 			ins.second = readNormalNr(bufor,i+ir*4+2, 2);
-			std::pair<int,std::pair<CCreature *, int> > tt(ir,ins);
+			std::pair<si32,std::pair<ui32,si32> > tt(ir,ins);
 			ret.slots.insert(tt);
 		}
 		i+=number*4;
@@ -188,16 +188,16 @@ CCreatureSet readCreatureSet(unsigned char * bufor, int &i, int number, bool ver
 	else
 	{
 		CCreatureSet ret;
-		std::pair<CCreature *, int> ins;
+		std::pair<ui32,si32> ins;
 		for(int ir=0;ir<number;ir++)
 		{
 			int rettt = readNormalNr(bufor,i+ir*3, 1);
 			if(rettt==0xff) continue;
 			if(rettt>220)
 				rettt = 256-rettt+VLC->creh->creatures.size()-16;
-			ins.first = &(VLC->creh->creatures[rettt]);
+			ins.first = rettt;
 			ins.second = readNormalNr(bufor,i+ir*3+1, 2);
-			std::pair<int,std::pair<CCreature *, int> > tt(ir,ins);
+			std::pair<si32,std::pair<ui32,si32> > tt(ir,ins);
 			ret.slots.insert(tt);
 		}
 		i+=number*3;
@@ -455,7 +455,7 @@ void Mapa::initFromBytes(unsigned char * bufor)
 	for (int ii=0;ii<width;ii++)
 	{
 		terrain[ii] = new TerrainTile*[height]; // allocate memory 
-		for(int jj=0;jj<=height;jj++)
+		for(int jj=0;jj<height;jj++)
 			terrain[ii][jj] = new TerrainTile[twoLevel+1];
 	}
 	int pom;
@@ -2342,6 +2342,7 @@ Mapa::Mapa(std::string filename)
 	std::cout<<"done."<<std::endl;
 	boost::crc_32_type  result;
 	result.process_bytes(initTable,mapstr.size());
+	checksum = result.checksum();
 	std::cout << "\tOur map checksum: "<<result.checksum() << std::endl;
 	initFromBytes(initTable);
 }

+ 52 - 3
server/CGameHandler.cpp

@@ -15,6 +15,7 @@
 #include "../hch/CTownHandler.h"
 #include "../hch/CHeroHandler.h"
 #include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types
+#include "../lib/VCMI_Lib.h"
 extern bool end;
 bool makingTurn;
 boost::condition_variable cTurn;
@@ -176,6 +177,54 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					sendAndApply(&tmh);
 					break;
 				}
+			case 502: //swap creatures in garrison
+				{
+					ui8 what, p1, p2; si32 id1, id2;
+					c >> what >> id1 >> p1 >> id2 >> p2;
+					CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1]),
+						*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2]);
+					CCreatureSet *S1 = &s1->army, *S2 = &s2->army;
+					
+					if(what==1) //swap
+					{
+						int pom = S2->slots[p2].first;
+						S2->slots[p2].first = S1->slots[p1].first;
+						S1->slots[p1].first = pom;
+						int pom2 = S2->slots[p2].second;
+						S2->slots[p2].second = S1->slots[p1].second;
+						S1->slots[p1].second = pom2;
+
+						if(!S1->slots[p1].first)
+							S1->slots.erase(p1);
+						if(!S2->slots[p2].first)
+							S2->slots.erase(p2);
+					}
+					else if(what==2)//merge
+					{
+						if(S1->slots[p1].first != S2->slots[p2].first) break; //not same creature
+						S2->slots[p2].second += S1->slots[p1].second;
+						S1->slots[p1].first = NULL;
+						S1->slots[p1].second = 0;
+						S1->slots.erase(p1);
+					}
+					else if(what==3) //split
+					{
+						si32 val;
+						c >> val;
+						if(S2->slots.find(p2) != S2->slots.end()) break; //slot not free
+						S2->slots[p2].first = S1->slots[p1].first;
+						S2->slots[p2].second = val;
+						S1->slots[p1].second -= val;
+						if(!S1->slots[p1].second) //if we've moved all creatures
+							S1->slots.erase(p1); 
+					}
+					SetGarrisons sg;
+					sg.garrs[id1] = *S1;
+					if(s1 != s2)
+						sg.garrs[id2] = *S2;
+					sendAndApply(&sg);
+					break;
+				}
 			default:
 				throw std::exception("Not supported client message!");
 				break;
@@ -241,11 +290,11 @@ void CGameHandler::init(StartInfo *si, int Seed)
 }
 int lowestSpeed(CGHeroInstance * chi)
 {
-	std::map<si32,std::pair<CCreature*,si32> >::iterator i = chi->army.slots.begin();
-	int ret = (*i++).second.first->speed;
+	std::map<si32,std::pair<ui32,si32> >::iterator i = chi->army.slots.begin();
+	int ret = VLC->creh->creatures[(*i++).second.first].speed;
 	for (;i!=chi->army.slots.end();i++)
 	{
-		ret = min(ret,(*i).second.first->speed);
+		ret = min(ret,VLC->creh->creatures[(*i).second.first].speed);
 	}
 	return ret;
 }

+ 77 - 0
server/VCMI_server.vcproj

@@ -162,6 +162,83 @@
 				Name="VCPostBuildEventTool"
 			/>
 		</Configuration>
+		<Configuration
+			Name="RD|Win32"
+			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+			IntermediateDirectory="$(ConfigurationName)"
+			ConfigurationType="1"
+			CharacterSet="2"
+			WholeProgramOptimization="1"
+			>
+			<Tool
+				Name="VCPreBuildEventTool"
+			/>
+			<Tool
+				Name="VCCustomBuildTool"
+			/>
+			<Tool
+				Name="VCXMLDataGeneratorTool"
+			/>
+			<Tool
+				Name="VCWebServiceProxyGeneratorTool"
+			/>
+			<Tool
+				Name="VCMIDLTool"
+			/>
+			<Tool
+				Name="VCCLCompilerTool"
+				Optimization="2"
+				EnableIntrinsicFunctions="true"
+				FavorSizeOrSpeed="1"
+				OmitFramePointers="true"
+				EnableFiberSafeOptimizations="true"
+				StringPooling="true"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="false"
+				WarningLevel="3"
+				DebugInformationFormat="3"
+				DisableSpecificWarnings="4251"
+			/>
+			<Tool
+				Name="VCManagedResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCResourceCompilerTool"
+			/>
+			<Tool
+				Name="VCPreLinkEventTool"
+			/>
+			<Tool
+				Name="VCLinkerTool"
+				AdditionalDependencies="VCMI_lib.lib  zdll.lib"
+				AdditionalLibraryDirectories="G:\vcmt\repa\libs"
+				GenerateDebugInformation="true"
+				OptimizeReferences="2"
+				EnableCOMDATFolding="2"
+				TargetMachine="1"
+			/>
+			<Tool
+				Name="VCALinkTool"
+			/>
+			<Tool
+				Name="VCManifestTool"
+			/>
+			<Tool
+				Name="VCXDCMakeTool"
+			/>
+			<Tool
+				Name="VCBscMakeTool"
+			/>
+			<Tool
+				Name="VCFxCopTool"
+			/>
+			<Tool
+				Name="VCAppVerifierTool"
+			/>
+			<Tool
+				Name="VCPostBuildEventTool"
+			/>
+		</Configuration>
 	</Configurations>
 	<References>
 	</References>