Преглед изворни кода

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

Michał W. Urbańczyk пре 17 година
родитељ
комит
5c5c80933b
15 измењених фајлова са 235 додато и 170 уклоњено
  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
 		//recruit
 		int slot = -1; //slot ID
 		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
 		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;
 				slot = i;
 				break;
 				break;
@@ -160,7 +160,7 @@ void CCallback::recruitCreatures(const CGObjectInstance *obj, int ID, int amount
 		}
 		}
 		else //create new stack in the garrison
 		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;
 			t->army.slots[slot].second = amount;
 		}
 		}
 		cl->playerint[player]->garrisonChanged(obj);
 		cl->playerint[player]->garrisonChanged(obj);
@@ -194,7 +194,7 @@ void CCallback::endTurn()
 UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
 UpgradeInfo CCallback::getUpgradeInfo(const CArmedInstance *obj, int stackPos)
 {
 {
 	UpgradeInfo ret;
 	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))
 	if((obj->ID == 98)  ||  ((obj->ID == 34) && static_cast<const CGHeroInstance*>(obj)->visitedTown))
 	{
 	{
 		CGTownInstance * t;
 		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)
 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;
 		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;
 	return 0;
 }
 }
 
 
 int CCallback::mergeStacks(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2)
 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;
 		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;
 	return 0;
 }
 }
 int CCallback::splitStack(const CGObjectInstance *s1, const CGObjectInstance *s2, int p1, int p2, int val)
 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;
 		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;
 	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;
 				players[h->getOwner()].fogOfWarMap[t.x][t.y][t.z] = 1;
 			break;
 			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
 	case 1001://set object property
 		{
 		{
 			SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
 			SetObjectProperty *p = static_cast<SetObjectProperty*>(pack);
@@ -568,7 +575,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 					}
 					}
 					continue;
 					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)
 				if((pom = (vhi->type->highStack[x]-vhi->type->lowStack[x])) > 0)
 					vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x];
 					vhi->army.slots[x-pom2].second = (ran()%pom)+vhi->type->lowStack[x];
 				else 
 				else 
@@ -674,7 +681,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 	curB->side2=(hero2)?(hero2->tempOwner):(-1);
 	curB->side2=(hero2)?(hero2->tempOwner):(-1);
 	curB->round = -2;
 	curB->round = -2;
 	curB->stackActionPerformed = false;
 	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.push_back(new CStack(i->second.first,i->second.second,0, stacks.size(), true));
 		stacks[stacks.size()-1]->ID = stacks.size()-1;
 		stacks[stacks.size()-1]->ID = stacks.size()-1;
@@ -729,7 +736,7 @@ void CGameState::battle(CCreatureSet * army1, CCreatureSet * army2, int3 tile, C
 	default: //fault
 	default: //fault
 		break;
 		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));
 		stacks.push_back(new CStack(i->second.first,i->second.second,1, stacks.size(), false));
 	switch(army2->slots.size()) //for defender
 	switch(army2->slots.size()) //for defender
 	{
 	{

+ 1 - 1
CLua.cpp

@@ -720,7 +720,7 @@ void CMonsterS::onHeroVisit(int objid, int heroID)
 	DEFOS;
 	DEFOS;
 	CCreatureSet set;
 	CCreatureSet set;
 	//TODO: zrobic secik w sposob wyrafinowany
 	//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);
 	cb->startBattle(heroID,&set,os->pos);
 }
 }
 std::vector<int> CMonsterS::yourObjects() //returns IDs of objects which are handled by script
 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));
 		sup = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL));
 		for
 		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++)
 			i!=set1->slots.end(); i++)
 		{
 		{
 			(*sup)[i->first] = 
 			(*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++)
 		for(int i=0; i<sup->size(); i++)
 			if((*sup)[i] == NULL)
 			if((*sup)[i] == NULL)
@@ -356,11 +356,11 @@ void CGarrisonInt::createSlots()
 	{	
 	{	
 		sdown = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL));
 		sdown = new std::vector<CGarrisonSlot*>(7,(CGarrisonSlot *)(NULL));
 		for
 		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++)
 			i!=set2->slots.end(); i++)
 		{
 		{
 			(*sdown)[i->first] = 
 			(*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++)
 		for(int i=0; i<sup->size(); i++)
 			if((*sdown)[i] == NULL)
 			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;
 	std::cout << "\tOur checksum for the map: "<< mapa->checksum << std::endl;
 
 
 	if(mapa->checksum != sum)
 	if(mapa->checksum != sum)
+	{
+		throw std::exception("Wrong checksum");
 		exit(-1);
 		exit(-1);
+	}
 	std::cout << "\tUsing random seed: "<<seed << std::endl;
 	std::cout << "\tUsing random seed: "<<seed << std::endl;
 
 
 	gs = CGI->state;
 	gs = CGI->state;
@@ -223,6 +226,15 @@ void CClient::process(int what)
 			mess.cv->notify_all();
 			mess.cv->notify_all();
 			break;
 			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:
 	case 1001:
 		{
 		{
 			SetObjectProperty sop;
 			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));
 	SDL_SetColorKey(ret,SDL_SRCCOLORKEY,SDL_MapRGB(ret->format,0,255,255));
 	printAt(curh->name,75,15,GEOR13,zwykly,ret);
 	printAt(curh->name,75,15,GEOR13,zwykly,ret);
 	drawPrimarySkill(curh, 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);
 		itoa((*i).second.second,buf,10);
 		printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+39,GEORM,zwykly,ret);
 		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);
 		blitAt(halls->ourImages[pom].bitmap,77,42,ret);
 	itoa(curh->dailyIncome(),buf,10);
 	itoa(curh->dailyIncome(),buf,10);
 	printAtMiddle(buf,167,70,GEORM,zwykly,ret);
 	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)
 		if(!i->second.first)
 			continue;
 			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);
 		itoa((*i).second.second,buf,10);
 		printAtMiddle(buf,slotsPos[(*i).first].first+17,slotsPos[(*i).first].second+39,GEORM,zwykly,ret);
 		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>
 		<Configuration
 		<Configuration
-			Name="Optibug|Win32"
+			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="1"
 			ConfigurationType="1"
@@ -199,10 +199,14 @@
 				EnableIntrinsicFunctions="true"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				OmitFramePointers="true"
+				EnableFiberSafeOptimizations="true"
+				WholeProgramOptimization="true"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				StringPooling="true"
 				StringPooling="true"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="false"
+				EnableEnhancedInstructionSet="0"
 				WarningLevel="3"
 				WarningLevel="3"
 				DebugInformationFormat="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"
 				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"
 				AdditionalLibraryDirectories="G:\vcmt\repa\libs"
 				GenerateDebugInformation="true"
 				GenerateDebugInformation="true"
+				Driver="0"
 				OptimizeReferences="2"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="2"
 				EnableCOMDATFolding="2"
+				LinkTimeCodeGeneration="0"
 				TargetMachine="1"
 				TargetMachine="1"
 			/>
 			/>
 			<Tool
 			<Tool

+ 2 - 2
hch/CObjectHandler.cpp

@@ -179,8 +179,8 @@ unsigned int CGHeroInstance::getLowestCreatureSpeed()
 	unsigned int sl = 100;
 	unsigned int sl = 100;
 	for(int h=0; h<army.slots.size(); ++h)
 	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;
 	return sl;
 }
 }

+ 6 - 2
int3.h

@@ -5,8 +5,12 @@ class CCreature;
 class CCreatureSet //seven combined creatures
 class CCreatureSet //seven combined creatures
 {
 {
 public:
 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
 class int3

+ 19 - 0
lib/Connection.h

@@ -262,6 +262,25 @@ public:
 	{
 	{
 		*this >> data.first >> data.second;
 		*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>
 	template <typename T>
 	void save(const T &data)
 	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;
 		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
 struct MetaString : public CPack<MetaString> //2001 helper for object scrips
 {
 {
 	std::vector<std::string> strings;
 	std::vector<std::string> strings;

+ 11 - 81
lib/VCMI_lib.vcproj

@@ -169,11 +169,11 @@
 			/>
 			/>
 		</Configuration>
 		</Configuration>
 		<Configuration
 		<Configuration
-			Name="Optibug_dll|Win32"
+			Name="RD|Win32"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			OutputDirectory="$(SolutionDir)$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			IntermediateDirectory="$(ConfigurationName)"
 			ConfigurationType="2"
 			ConfigurationType="2"
-			CharacterSet="2"
+			CharacterSet="1"
 			WholeProgramOptimization="1"
 			WholeProgramOptimization="1"
 			>
 			>
 			<Tool
 			<Tool
@@ -193,18 +193,20 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCCLCompilerTool"
 				Name="VCCLCompilerTool"
-				Optimization="0"
+				Optimization="3"
 				EnableIntrinsicFunctions="true"
 				EnableIntrinsicFunctions="true"
 				FavorSizeOrSpeed="1"
 				FavorSizeOrSpeed="1"
 				OmitFramePointers="true"
 				OmitFramePointers="true"
 				EnableFiberSafeOptimizations="true"
 				EnableFiberSafeOptimizations="true"
+				WholeProgramOptimization="true"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				AdditionalIncludeDirectories="G:\vcmt\repa\include"
 				StringPooling="true"
 				StringPooling="true"
 				MinimalRebuild="false"
 				MinimalRebuild="false"
-				RuntimeLibrary="0"
-				EnableFunctionLevelLinking="true"
+				BasicRuntimeChecks="0"
+				RuntimeLibrary="2"
+				EnableFunctionLevelLinking="false"
 				WarningLevel="3"
 				WarningLevel="3"
-				DebugInformationFormat="4"
+				DebugInformationFormat="3"
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCManagedResourceCompilerTool"
 				Name="VCManagedResourceCompilerTool"
@@ -217,85 +219,13 @@
 			/>
 			/>
 			<Tool
 			<Tool
 				Name="VCLinkerTool"
 				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"
 				AdditionalLibraryDirectories="G:\vcmt\repa\libs"
 				GenerateDebugInformation="true"
 				GenerateDebugInformation="true"
 				OptimizeReferences="2"
 				OptimizeReferences="2"
 				EnableCOMDATFolding="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"
 				TargetMachine="1"
 			/>
 			/>
 			<Tool
 			<Tool

+ 8 - 7
map.cpp

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

+ 52 - 3
server/CGameHandler.cpp

@@ -15,6 +15,7 @@
 #include "../hch/CTownHandler.h"
 #include "../hch/CTownHandler.h"
 #include "../hch/CHeroHandler.h"
 #include "../hch/CHeroHandler.h"
 #include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types
 #include "boost/date_time/posix_time/posix_time_types.hpp" //no i/o just types
+#include "../lib/VCMI_Lib.h"
 extern bool end;
 extern bool end;
 bool makingTurn;
 bool makingTurn;
 boost::condition_variable cTurn;
 boost::condition_variable cTurn;
@@ -176,6 +177,54 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 					sendAndApply(&tmh);
 					sendAndApply(&tmh);
 					break;
 					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:
 			default:
 				throw std::exception("Not supported client message!");
 				throw std::exception("Not supported client message!");
 				break;
 				break;
@@ -241,11 +290,11 @@ void CGameHandler::init(StartInfo *si, int Seed)
 }
 }
 int lowestSpeed(CGHeroInstance * chi)
 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++)
 	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;
 	return ret;
 }
 }

+ 77 - 0
server/VCMI_server.vcproj

@@ -162,6 +162,83 @@
 				Name="VCPostBuildEventTool"
 				Name="VCPostBuildEventTool"
 			/>
 			/>
 		</Configuration>
 		</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>
 	</Configurations>
 	<References>
 	<References>
 	</References>
 	</References>