Bladeren bron

Further serialization code and refactorings.

Michał W. Urbańczyk 17 jaren geleden
bovenliggende
commit
847a4f222c
17 gewijzigde bestanden met toevoegingen van 778 en 725 verwijderingen
  1. 15 10
      CGameState.cpp
  2. 6 2
      CGameState.h
  3. 11 6
      CPreGame.cpp
  4. 1 1
      client/Client.cpp
  5. 4 3
      hch/CBuildingHandler.cpp
  6. 1 0
      hch/CDefObjInfoHandler.cpp
  7. 11 10
      hch/CDefObjInfoHandler.h
  8. 81 5
      hch/CGeneralTextHandler.cpp
  9. 10 1
      hch/CGeneralTextHandler.h
  10. 3 81
      hch/CObjectHandler.cpp
  11. 154 70
      hch/CObjectHandler.h
  12. 22 1
      lib/Connection.cpp
  13. 32 18
      lib/Connection.h
  14. 192 433
      map.cpp
  15. 211 78
      map.h
  16. 10 3
      mapHandler.cpp
  17. 14 3
      server/CGameHandler.cpp

+ 15 - 10
CGameState.cpp

@@ -55,12 +55,12 @@ std::string DLL_EXPORT toString(MetaString &ms)
 			}
 			else if(type == 9)
 			{
-				ret += VLC->objh->mines[ser].first;
+				ret += VLC->generaltexth->mines[ser].first;
 				continue;
 			}
 			else if(type == 10)
 			{
-				ret += VLC->objh->mines[ser].second;
+				ret += VLC->generaltexth->mines[ser].second;
 				continue;
 			}
 			else
@@ -71,22 +71,22 @@ std::string DLL_EXPORT toString(MetaString &ms)
 					vec = &VLC->generaltexth->allTexts;
 					break;
 				case 2:
-					vec = &VLC->objh->xtrainfo;
+					vec = &VLC->generaltexth->xtrainfo;
 					break;
 				case 3:
-					vec = &VLC->objh->names;
+					vec = &VLC->generaltexth->names;
 					break;
 				case 4:
-					vec = &VLC->objh->restypes;
+					vec = &VLC->generaltexth->restypes;
 					break;
 				case 6:
 					vec = &VLC->generaltexth->arraytxt;
 					break;
 				case 8:
-					vec = &VLC->objh->creGens;
+					vec = &VLC->generaltexth->creGens;
 					break;
 				case 11:
-					vec = &VLC->objh->advobtxt;
+					vec = &VLC->generaltexth->advobtxt;
 					break;
 				case 12:
 					vec = &VLC->generaltexth->artifEvents;
@@ -1084,7 +1084,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
 	//we have to replace normal random object
 	cur->ID = ran.first;
 	cur->subID = ran.second;
-	map->defs.insert(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]);
+	map->defy.push_back(cur->defInfo = VLC->dobjinfo->gobjs[ran.first][ran.second]);
 	if(!cur->defInfo)
 	{
 		tlog1<<"*BIG* WARNING: Missing def declaration for "<<cur->ID<<" "<<cur->subID<<std::endl;
@@ -1159,7 +1159,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 			map->objects[no]->defInfo->blockMap[5] = 255;
 			map->addBlockVisTiles(map->objects[no]);
 		}
-		map->objects[no]->hoverName = VLC->objh->names[map->objects[no]->ID];
+		map->objects[no]->hoverName = VLC->generaltexth->names[map->objects[no]->ID];
 	}
 	//std::cout<<"\tRandomizing objects: "<<th.getDif()<<std::endl;
 
@@ -1245,7 +1245,7 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 	for(int i=0; i<map->allowedHeroes.size(); i++) //add to hids all allowed heroes
 		if(map->allowedHeroes[i])
 			hids.insert(i);
-	for (int i=0; i<map->heroes.size();i++) //heroes instances
+	for (int i=0; i<map->heroes.size();i++) //heroes instances initialization
 	{
 		if (map->heroes[i]->getOwner()<0)
 		{
@@ -1452,6 +1452,11 @@ void CGameState::init(StartInfo * si, Mapa * map, int Seed)
 		}
 	}
 
+	for(int i=0; i<map->defy.size(); i++)
+	{
+		map->defy[i]->serial = i;
+	}
+
 	for(int i=0; i<map->objects.size(); i++)
 		map->objects[i]->initObj();
 }

+ 6 - 2
CGameState.h

@@ -178,6 +178,11 @@ private:
 		std::map<ui32,ui8> pavailable; // [subid] -> which players can recruit hero
 
 		CGHeroInstance * pickHeroFor(bool native, int player, const CTown *town, int notThatOne=-1);
+
+		template <typename Handler> void serialize(Handler &h, const int version)
+		{
+			h & heroesPool & pavailable;
+		}
 	} hpool; //we have here all heroes available on this map that are not hired
 
 	boost::shared_mutex *mx;
@@ -208,12 +213,11 @@ public:
 	int getDate(int mode=0) const; //mode=0 - total days in game, mode=1 - day of week, mode=2 - current week, mode=3 - current month
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & scenarioOps & seed & currentPlayer & day & map & players & resVals;
+		h & scenarioOps & seed & currentPlayer & day & map & players & resVals & hpool;
 		if(!h.saving)
 		{
 			loadTownDInfos();
 		}
-		//TODO: hero pool
 	}
 
 	friend class CCallback;

+ 11 - 6
CPreGame.cpp

@@ -922,13 +922,18 @@ void MapSel::printMaps(int from, int to, int at, bool abs)
 		if (!(ourMaps[(i-at)+from].name.length()))
 			ourMaps[(i-at)+from].name = "Unnamed";
 		CSDL_Ext::printAtMiddle(ourMaps[(i-at)+from].name,192,13,GEOR13,nasz,scenin, 2);
-		if (ourMaps[(i-at)+from].victoryCondition==winStandard)
+		if (ourMaps[(i-at)+from].victoryCondition.condition == winStandard)
 			temp=11;
-		else temp=ourMaps[(i-at)+from].victoryCondition;
+		else 
+			temp=ourMaps[(i-at)+from].victoryCondition.condition;
+
 		blitAt(Dvic->ourImages[temp].bitmap,285,2,scenin);
+
 		if (ourMaps[(i-at)+from].lossCondition.typeOfLossCon == lossStandard)
 			temp=3;
-		else temp=ourMaps[(i-at)+from].lossCondition.typeOfLossCon;
+		else 
+			temp=ourMaps[(i-at)+from].lossCondition.typeOfLossCon;
+
 		blitAt(Dloss->ourImages[temp].bitmap,318,2,scenin);
 
 		blitAt(scenin,24,121+(i-at)*25);
@@ -1251,10 +1256,10 @@ void MapSel::printSelectedInfo()
 	CSDL_Ext::printAt(CGI->generaltexth->allTexts[390],420,406,GEOR13,zwykly);
 	CSDL_Ext::printAt(CGI->generaltexth->allTexts[391],585,406,GEOR13,zwykly);
 
-	int temp = ourMaps[selected].victoryCondition+1;
+	int temp = ourMaps[selected].victoryCondition.condition+1;
 	if (temp>20) temp=0;
 	std::string sss = CGI->generaltexth->victoryConditions[temp];
-	if (temp && ourMaps[selected].vicConDetails->allowNormalVictory) sss+= "/" + CGI->generaltexth->victoryConditions[0];
+	if (temp && ourMaps[selected].victoryCondition.allowNormalVictory) sss+= "/" + CGI->generaltexth->victoryConditions[0];
 	CSDL_Ext::printAt(sss,452,310,GEOR13,zwykly);
 
 
@@ -1312,7 +1317,7 @@ void MapSel::printSelectedInfo()
 		break;
 	}
 	blitAt(Dsizes->ourImages[temp].bitmap,714,28);
-	temp=ourMaps[selected].victoryCondition;
+	temp = ourMaps[selected].victoryCondition.condition;
 	if (temp>12) temp=11;
 	blitAt(Dvic->ourImages[temp].bitmap,420,308); //v
 	temp=ourMaps[selected].lossCondition.typeOfLossCon;

+ 1 - 1
client/Client.cpp

@@ -120,7 +120,7 @@ void CClient::process(int what)
 		{
 			SetResource sr;
 			*serv >> sr;
-			tlog5 << "Set amount of "<<CGI->objh->restypes[sr.resid] 
+			tlog5 << "Set amount of "<<CGI->generaltexth->restypes[sr.resid] 
 			  << " of player "<<(unsigned)sr.player <<" to "<<sr.val<<std::endl;
 			gs->apply(&sr);
 			playerint[sr.player]->receivedResource(sr.resid,sr.val);

+ 4 - 3
hch/CBuildingHandler.cpp

@@ -7,7 +7,7 @@
 #include <sstream>
 #include <fstream>
 extern CLodHandler * bitmaph;
-unsigned int readNr(std::string &in, unsigned int &it)
+unsigned int readNr(std::string &in, int &it)
 {
 	int last=it;
 	for(;last<in.size();last++)
@@ -24,7 +24,7 @@ unsigned int readNr(std::string &in, unsigned int &it)
 	ss >> last;
 	return last;
 }
-CBuilding * readBg(std::string &buf, unsigned int& it)
+CBuilding * readBg(std::string &buf, int& it)
 {
 	CBuilding * nb = new CBuilding();
 	nb->resources.resize(RESOURCE_QUANTITY);
@@ -37,7 +37,8 @@ CBuilding * readBg(std::string &buf, unsigned int& it)
 void CBuildingHandler::loadBuildings()
 {
 	std::string buf = bitmaph->getTextFile("BUILDING.TXT"), temp;
-	unsigned int andame = buf.size(), it=0; //buf iterator
+	unsigned int andame = buf.size();
+	int it=0; //buf iterator
 
 	temp = readTo(buf,it,'\n');temp = readTo(buf,it,'\n');//read 2 lines of file info
 

+ 1 - 0
hch/CDefObjInfoHandler.cpp

@@ -18,6 +18,7 @@ bool CGDefInfo::isVisitable()
 }
 CGDefInfo::CGDefInfo()
 {
+	serial = -1;
 	visitDir = (8|16|32|64|128); //4,5,6,7,8 - any not-from-up direction
 }
 void CDefObjInfoHandler::load()

+ 11 - 10
hch/CDefObjInfoHandler.h

@@ -10,16 +10,17 @@ class DLL_EXPORT CGDefInfo
 public:
 	std::string name;
 
-	unsigned char visitMap[6];
-	unsigned char blockMap[6];
-	unsigned char visitDir; //directions from which object can be entered, format same as for moveDir in CGHeroInstance(but 0 - 7)
-	int id, subid; //of object described by this defInfo
-	int terrainAllowed, //on which terrain it is possible to place object
+	ui8 visitMap[6];
+	ui8 blockMap[6];
+	ui8 visitDir; //directions from which object can be entered, format same as for moveDir in CGHeroInstance(but 0 - 7)
+	si32 id, subid; //of object described by this defInfo
+	si32 serial;
+	si32 terrainAllowed, //on which terrain it is possible to place object
 		 terrainMenu; //in which menus in map editor object will be showed
-	int width, height; //tiles
-	int type; //(0- ground, 1- towns, 2-creatures, 3- heroes, 4-artifacts, 5- resources)   
+	si32 width, height; //tiles
+	si32 type; //(0- ground, 1- towns, 2-creatures, 3- heroes, 4-artifacts, 5- resources)   
 	CDefHandler * handler;
-	int printPriority;
+	si32 printPriority;
 	bool isVisitable();
 	bool operator<(const CGDefInfo& por)
 	{
@@ -30,7 +31,8 @@ public:
 	}
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & name & visitMap & blockMap & visitDir & id & subid &terrainAllowed & terrainMenu & width & height & type & printPriority;
+		h & name & serial & visitMap & blockMap & visitDir & id & subid &terrainAllowed
+			& terrainMenu & width & height & type & printPriority;
 	}
 	CGDefInfo();
 };
@@ -39,7 +41,6 @@ class DLL_EXPORT CDefObjInfoHandler
 public:
 	std::map<int,std::map<int,CGDefInfo*> > gobjs;
 	std::map<int,CGDefInfo*> castles;
-	//std::vector<DefObjInfo> objs;
 	void load();
 
 

+ 81 - 5
hch/CGeneralTextHandler.cpp

@@ -8,7 +8,7 @@
 #include <fstream>
 #include <sstream>
 
-std::string readTo(std::string &in, unsigned int &it, char end)
+std::string readTo(std::string &in, int &it, char end)
 {
 	int pom = it;
 	int last = in.find_first_of(end,it);
@@ -174,7 +174,7 @@ void CGeneralTextHandler::loadTexts()
 		loadToIt(hTxts[iii].biography,buf,i,3);
 	}
 
-	unsigned it;
+	int it;
 	buf = bitmaph->getTextFile("BLDGNEUT.TXT");
 	andame = buf.size(), it=0;
 
@@ -250,9 +250,9 @@ void CGeneralTextHandler::loadTexts()
 		hcommands.push_back(tmp);
 	}
 
-	std::istringstream ins, names;
+	std::istringstream ins, namess;
 	ins.str(bitmaph->getTextFile("TOWNTYPE.TXT"));
-	names.str(bitmaph->getTextFile("TOWNNAME.TXT"));
+	namess.str(bitmaph->getTextFile("TOWNNAME.TXT"));
 	int si=0;
 	char bufname[75];
 	while (!ins.eof())
@@ -263,9 +263,85 @@ void CGeneralTextHandler::loadTexts()
 
 		for (int i=0; i<NAMES_PER_TOWN; i++)
 		{
-			names.getline(bufname,50);
+			namess.getline(bufname,50);
 			townNames[si].push_back(std::string(bufname).substr(0,strlen(bufname)-1));
 		}
 		si++;
 	}
+
+	tlog5 << "\t\tReading OBJNAMES \n";
+	buf = bitmaph->getTextFile("OBJNAMES.TXT");
+	it=0; //hope that -1 will not break this
+	while (it<buf.length()-1)
+	{
+		std::string nobj;
+		loadToIt(nobj, buf, it, 3);
+		if(nobj.size() && (nobj[nobj.size()-1]==(char)10 || nobj[nobj.size()-1]==(char)13 || nobj[nobj.size()-1]==(char)9))
+		{
+			nobj = nobj.substr(0, nobj.size()-1);
+		}
+		names.push_back(nobj);
+	}
+
+	tlog5 << "\t\tReading ADVEVENT \n";
+	buf = bitmaph->getTextFile("ADVEVENT.TXT");
+	it=0;
+	std::string temp;
+	while (it<buf.length()-1)
+	{
+		loadToIt(temp,buf,it,3);
+		if (temp[0]=='\"')
+		{
+			temp = temp.substr(1,temp.length()-2);
+		}
+		boost::algorithm::replace_all(temp,"\"\"","\"");
+		advobtxt.push_back(temp);
+	}
+
+	tlog5 << "\t\tReading XTRAINFO \n";
+	buf = bitmaph->getTextFile("XTRAINFO.TXT");
+	it=0;
+	while (it<buf.length()-1)
+	{
+		loadToIt(temp,buf,it,3);
+		xtrainfo.push_back(temp);
+	}
+
+	tlog5 << "\t\tReading MINENAME \n";
+	buf = bitmaph->getTextFile("MINENAME.TXT");
+	it=0;
+	while (it<buf.length()-1)
+	{
+		loadToIt(temp,buf,it,3);
+		mines.push_back(std::pair<std::string,std::string>(temp,""));
+	}
+
+	tlog5 << "\t\tReading MINEEVNT \n";
+	buf = bitmaph->getTextFile("MINEEVNT.TXT");
+	it=0;
+	i=0;
+	while (it<buf.length()-1)
+	{
+		loadToIt(temp,buf,it,3);
+		temp = temp.substr(1,temp.length()-2);
+		mines[i++].second = temp;
+	}
+
+	tlog5 << "\t\tReading RESTYPES \n";
+	buf = bitmaph->getTextFile("RESTYPES.TXT");
+	it=0;
+	while (it<buf.length()-1)
+	{
+		loadToIt(temp,buf,it,3);
+		restypes.push_back(temp);
+	}	
+	
+	tlog5 << "\t\tReading ZCRGN1 \n";
+	buf = bitmaph->getTextFile("ZCRGN1.TXT");
+	it=0;
+	while (it<buf.length()-1)
+	{
+		loadToIt(temp,buf,it,3);
+		creGens.push_back(temp);
+	}
 }

+ 10 - 1
hch/CGeneralTextHandler.h

@@ -4,7 +4,7 @@
 #include <string>
 #include <vector>
 DLL_EXPORT void loadToIt(std::string &dest, std::string &src, int &iter, int mode);
-std::string readTo(std::string &in, unsigned int &it, char end);
+std::string readTo(std::string &in, int &it, char end);
 class DLL_EXPORT CGeneralTextHandler //Handles general texts
 {
 public:
@@ -37,6 +37,15 @@ public:
 	std::vector<std::pair<std::string,std::string> > zelp;
 	std::string lossCondtions[4];
 	std::string victoryConditions[14];
+
+	//objects
+	std::vector<std::string> names; //vector of objects; i-th object in vector has subnumber i
+	std::vector<std::string> creGens; //names of creatures' generators
+	std::vector<std::string> advobtxt;
+	std::vector<std::string> xtrainfo;
+	std::vector<std::string> restypes;
+	std::vector<std::pair<std::string,std::string> > mines; //first - name; second - event description
+
 
 	std::string getTitle(std::string text);
 	std::string getDescr(std::string text);

+ 3 - 81
hch/CObjectHandler.cpp

@@ -44,75 +44,6 @@ void IObjectInterface::initObj()
 
 void CObjectHandler::loadObjects()
 {
-	VLC->objh = this;
-//	int ID=0; //TODO use me
-	tlog5 << "\t\tReading OBJNAMES \n";
-	std::string buf = bitmaph->getTextFile("OBJNAMES.TXT");
-	int it=0; //hope that -1 will not break this
-	while (it<buf.length()-1)
-	{
-		std::string nobj;
-		loadToIt(nobj, buf, it, 3);
-		if(nobj.size() && (nobj[nobj.size()-1]==(char)10 || nobj[nobj.size()-1]==(char)13 || nobj[nobj.size()-1]==(char)9))
-		{
-			nobj = nobj.substr(0, nobj.size()-1);
-		}
-		names.push_back(nobj);
-	}
-
-	tlog5 << "\t\tReading ADVEVENT \n";
-	buf = bitmaph->getTextFile("ADVEVENT.TXT");
-	it=0;
-	std::string temp;
-	while (it<buf.length()-1)
-	{
-		loadToIt(temp,buf,it,3);
-		if (temp[0]=='\"')
-		{
-			temp = temp.substr(1,temp.length()-2);
-		}
-		boost::algorithm::replace_all(temp,"\"\"","\"");
-		advobtxt.push_back(temp);
-	}
-
-	tlog5 << "\t\tReading XTRAINFO \n";
-	buf = bitmaph->getTextFile("XTRAINFO.TXT");
-	it=0;
-	while (it<buf.length()-1)
-	{
-		loadToIt(temp,buf,it,3);
-		xtrainfo.push_back(temp);
-	}
-
-	tlog5 << "\t\tReading MINENAME \n";
-	buf = bitmaph->getTextFile("MINENAME.TXT");
-	it=0;
-	while (it<buf.length()-1)
-	{
-		loadToIt(temp,buf,it,3);
-		mines.push_back(std::pair<std::string,std::string>(temp,""));
-	}
-
-	tlog5 << "\t\tReading MINEEVNT \n";
-	buf = bitmaph->getTextFile("MINEEVNT.TXT");
-	it=0;
-	int i=0;
-	while (it<buf.length()-1)
-	{
-		loadToIt(temp,buf,it,3);
-		temp = temp.substr(1,temp.length()-2);
-		mines[i++].second = temp;
-	}
-
-	tlog5 << "\t\tReading RESTYPES \n";
-	buf = bitmaph->getTextFile("RESTYPES.TXT");
-	it=0;
-	while (it<buf.length()-1)
-	{
-		loadToIt(temp,buf,it,3);
-		restypes.push_back(temp);
-	}
-
 	tlog5 << "\t\tReading cregens \n";
 	cregens.resize(110); //TODO: hardcoded value - change
 	for(size_t i=0; i < cregens.size(); ++i)
@@ -128,15 +59,6 @@ void CObjectHandler::loadObjects()
 	}
 	ifs.close();
 	ifs.clear();
-
-	tlog5 << "\t\tReading ZCRGN1 \n";
-	buf = bitmaph->getTextFile("ZCRGN1.TXT");
-	it=0;
-	while (it<buf.length()-1)
-	{
-		loadToIt(temp,buf,it,3);
-		creGens.push_back(temp);
-	}
 	tlog5 << "\t\tDone loading objects!\n";
 }
 int CGObjectInstance::getOwner() const
@@ -994,7 +916,7 @@ const std::string & CGVisitableOPH::getHoverText() const
 	default:
 		throw "Wrong CGVisitableOPH object ID!\n";
 	}
-	hoverName = VLC->objh->names[ID] + " " + VLC->objh->xtrainfo[pom];
+	hoverName = VLC->generaltexth->names[ID] + " " + VLC->generaltexth->xtrainfo[pom];
 	const CGHeroInstance *h = cb->getSelectedHero(cb->getCurrentPlayer());
 	if(h)
 	{
@@ -1110,7 +1032,7 @@ void CGMine::initObj()
 void CGResource::initObj()
 {
 	blockVisit = true;
-	hoverName = VLC->objh->restypes[subID];
+	hoverName = VLC->generaltexth->restypes[subID];
 
 	if(!amount)
 	{
@@ -1146,7 +1068,7 @@ void CGResource::onHeroVisit( const CGHeroInstance * h ) const
 	sii.player = h->tempOwner;
 	sii.c = Component(2,subID,amount,0);
 	sii.text << std::pair<ui8,ui32>(11,113);
-	sii.text.replacements.push_back(VLC->objh->restypes[subID]);
+	sii.text.replacements.push_back(VLC->generaltexth->restypes[subID]);
 	cb->showCompInfo(&sii);
 	cb->removeObject(id);
 }

+ 154 - 70
hch/CObjectHandler.h

@@ -119,7 +119,7 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & hoverName & pos & ID & subID & id & animPhaseShift & tempOwner & blockVisit;
-		//TODO: definfo
+		//definfo is handled by map serializer
 	}
 };
 
@@ -131,6 +131,7 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
+		h & static_cast<CGObjectInstance&>(*this);
 		h & army;
 	}
 };
@@ -176,10 +177,17 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
+		h & static_cast<CArmedInstance&>(*this);
 		h & exp & level & name & biography & portrait & mana & primSkills & secSkills & movement
 			& identifier & sex & inTownGarrison & artifacts & artifWorn & spells;
-		//TODO: type
-		//TODO: visited town
+
+		ui8 standardType = (VLC->heroh->heroes[subID] == type);
+		h & standardType;
+		if(!standardType)
+			h & type;
+		else if(!h.saving)
+			type = VLC->heroh->heroes[subID];
+		//visitied town pointer will be restored by map serialization method
 	}
 
 	//////////////////////////////////////////////////////////////////////////
@@ -246,10 +254,18 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
+		h & static_cast<CArmedInstance&>(*this);
 		h & name & builded & destroyed & identifier & alignment & forbiddenBuildings & builtBuildings
 			& possibleSpells & obligatorySpells & spells & strInfo & events;
-		//TODO: town
-		//TODO: garrison/visiting hero
+
+		ui8 standardType = (&VLC->townh->towns[subID] == town);
+		h & standardType;
+		if(!standardType)
+			h & town;
+		else if(!h.saving)
+			town = &VLC->townh->towns[subID];
+
+		//garrison/visiting hero pointers will be restored in the map serialization
 	}
 
 	//////////////////////////////////////////////////////////////////////////
@@ -290,32 +306,41 @@ public:
 	void onNAHeroVisit(int heroID, bool alreadyVisited) const;
 	void initObj();
 	void treeSelected(int heroID, int resType, int resVal, int expVal, ui32 result) const; //handle player's anwer to the Tree of Knowledge dialog
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & visitors & ttype;
+	}
 };
 
 class DLL_EXPORT CGEvent : public CGObjectInstance //event objects
 {
 public:
-	bool areGuarders; //true if there are
 	CCreatureSet guarders;
-	bool isMessage; //true if there is a message
 	std::string message;
-	unsigned int gainedExp;
-	int manaDiff; //amount of gained / lost mana
-	int moraleDiff; //morale modifier
-	int luckDiff; //luck modifier
-	int wood, mercury, ore, sulfur, crystal, gems, gold; //gained / lost resources
-	unsigned int attack; //added attack points
-	unsigned int defence; //added defence points
-	unsigned int power; //added power points
-	unsigned int knowledge; //added knowledge points
-	std::vector<int> abilities; //gained abilities
-	std::vector<int> abilityLevels; //levels of gained abilities
-	std::vector<int> artifacts; //gained artifacts
-	std::vector<int> spells; //gained spells
+	ui32 gainedExp;
+	si32 manaDiff; //amount of gained / lost mana
+	si32 moraleDiff; //morale modifier
+	si32 luckDiff; //luck modifier
+	std::vector<si32> resources;//gained / lost resources
+	std::vector<si32> primskills;//gained / lost resources
+	std::vector<si32> abilities; //gained abilities
+	std::vector<si32> abilityLevels; //levels of gained abilities
+	std::vector<si32> artifacts; //gained artifacts
+	std::vector<si32> spells; //gained spells
 	CCreatureSet creatures; //gained creatures
-	unsigned char availableFor; //players whom this event is available for
-	bool computerActivate; //true if computre player can activate this event
-	bool humanActivate; //true if human player can activate this event
+	ui8 availableFor; //players whom this event is available for
+	ui8 computerActivate; //true if computre player can activate this event
+	ui8 humanActivate; //true if human player can activate this event
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & guarders & message & gainedExp & manaDiff & moraleDiff & luckDiff & resources & primskills
+			& abilities & abilityLevels & artifacts & spells & creatures & availableFor 
+			& computerActivate & humanActivate;
+	}
 };
 
 class DLL_EXPORT CGCreature : public CArmedInstance //creatures on map
@@ -332,6 +357,12 @@ public:
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void endBattle(BattleResult *result) const;
 	void initObj();
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CArmedInstance&>(*this);
+		h & identifier & character & message & resources & gainedArtifact & neverFlees & notGrowingTeam;
+	}
 }; 
 
 
@@ -340,42 +371,39 @@ class DLL_EXPORT CGSignBottle : public CGObjectInstance //signs and ocean bottle
 	//TODO: generate default message if sign is 'empty'
 public:
 	std::string message;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & message;
+	}
 };
 
 class DLL_EXPORT CGSeerHut : public CGObjectInstance, public CQuest
 {
 public:
-	char rewardType; //type of reward: 0 - no reward; 1 - experience; 2 - mana points; 3 - morale bonus; 4 - luck bonus; 5 - resources; 6 - main ability bonus (attak, defence etd.); 7 - secondary ability gain; 8 - artifact; 9 - spell; 10 - creature
-	//for reward 1
-	int r1exp;
-	//for reward 2
-	int r2mana;
-	//for reward 3
-	int r3morale;
-	//for reward 4
-	int r4luck;
-	//for reward 5
-	unsigned char r5type; //0 - wood, 1 - mercury, 2 - ore, 3 - sulfur, 4 - crystal, 5 - gems, 6 - gold
-	int r5amount;
-	//for reward 6
-	unsigned char r6type; //0 - attack, 1 - defence, 2 - power, 3 - knowledge
-	int r6amount;
-	//for reward 7
-	int r7ability; //ability id
-	unsigned char r7level; //1 - basic, 2 - advanced, 3 - expert
-	//for reward 8
-	int r8art;//artifact id
-	//for reward 9
-	int r9spell;//spell id
-	//for reward 10
-	int r10creature; //creature id
-	int r10amount;
+	ui8 rewardType; //type of reward: 0 - no reward; 1 - experience; 2 - mana points; 3 - morale bonus; 4 - luck bonus; 5 - resources; 6 - main ability bonus (attak, defence etd.); 7 - secondary ability gain; 8 - artifact; 9 - spell; 10 - creature
+
+	si32 rID;
+	si32 rVal;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this) & static_cast<CQuest&>(*this);
+		h & rewardType & rID & rVal;
+	}
 };
 
 class DLL_EXPORT CGWitchHut : public CGObjectInstance
 {
 public:
-	std::vector<int> allowedAbilities;
+	std::vector<si32> allowedAbilities;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & allowedAbilities;
+	}
 };
 
 
@@ -387,12 +415,24 @@ public:
 	ui8 r0type;
 	ui32 r1; //Ability ID
 	ui32 r2; //Spell ID
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & bonusType & r0type & r1 & r2;
+	}
 };
 
 class DLL_EXPORT CGGarrison : public CArmedInstance
 {
 public:
-	bool removableUnits;
+	ui8 removableUnits;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CArmedInstance&>(*this);
+		h & removableUnits;
+	}
 };
 
 class DLL_EXPORT CGArtifact : public CArmedInstance
@@ -402,31 +442,56 @@ public:
 	ui32 spell; //if it's spell scroll
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void initObj();	
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CArmedInstance&>(*this);
+		h & message & spell;
+	}
 };
 
 class DLL_EXPORT CGResource : public CArmedInstance
 {
 public:
-	int amount; //0 if random
+	ui32 amount; //0 if random
 	std::string message;
 
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void initObj();
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CArmedInstance&>(*this);
+		h & amount & message;
+	}
 };
 
 class DLL_EXPORT CGPickable : public CGObjectInstance //campfire, treasure chest
 {
+public:
 	ui32 type, val1, val2;
 
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void initObj();
 	void chosen(int which, int heroID) const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & type & val1 & val2;
+	}
 };
 
 class DLL_EXPORT CGShrine : public CGObjectInstance
 {
 public:
-	unsigned char spell; //number of spell or 255 if random
+	ui8 spell; //number of spell or 255 if random
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & spell;
+	}
 };
 
 class DLL_EXPORT CGPandoraBox : public CArmedInstance
@@ -435,22 +500,33 @@ public:
 	std::string message;
 
 	//gained things:
-	unsigned int gainedExp;
-	int manaDiff;
-	int moraleDiff;
-	int luckDiff;
-	int wood, mercury, ore, sulfur, crystal, gems, gold;
-	int attack, defence, power, knowledge;
-	std::vector<int> abilities;
-	std::vector<int> abilityLevels;
-	std::vector<int> artifacts;
-	std::vector<int> spells;
-	CCreatureSet creatures;
+	ui32 gainedExp;
+	si32 manaDiff; //amount of gained / lost mana
+	si32 moraleDiff; //morale modifier
+	si32 luckDiff; //luck modifier
+	std::vector<si32> resources;//gained / lost resources
+	std::vector<si32> primskills;//gained / lost resources
+	std::vector<si32> abilities; //gained abilities
+	std::vector<si32> abilityLevels; //levels of gained abilities
+	std::vector<si32> artifacts; //gained artifacts
+	std::vector<si32> spells; //gained spells
+	CCreatureSet creatures; //gained creatures
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CArmedInstance&>(*this);
+		h & message & gainedExp & manaDiff & moraleDiff & luckDiff & resources & primskills
+			& abilities & abilityLevels & artifacts & spells & creatures;
+	}
 };
 
 class DLL_EXPORT CGQuestGuard : public CGObjectInstance, public CQuest
 {
 public:
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CQuest&>(*this) & static_cast<CGObjectInstance&>(*this);
+	}
 };
 
 class DLL_EXPORT CGMine : public CArmedInstance
@@ -459,6 +535,10 @@ public:
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void newTurn() const;
 	void initObj();	
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CArmedInstance&>(*this);
+	}
 };
 
 class DLL_EXPORT CGVisitableOPW : public CGObjectInstance //objects visitable OPW
@@ -468,6 +548,12 @@ public:
 
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void newTurn() const;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+		h & visited;
+	}
 };
 
 class DLL_EXPORT CGTeleport : public CGObjectInstance //teleports and subterranean gates
@@ -476,20 +562,18 @@ public:
 	static std::map<int,std::map<int, std::vector<int> > > objs; //map[ID][subID] => vector of ids
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void initObj();	
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGObjectInstance&>(*this);
+	}
 };
 
 class DLL_EXPORT CObjectHandler
 {
 public:
-	std::vector<std::string> names; //vector of objects; i-th object in vector has subnumber i
 	std::vector<int> cregens; //type 17. dwelling subid -> creature ID
 	void loadObjects();
-
-	std::vector<std::string> creGens; //names of creatures' generators
-	std::vector<std::string> advobtxt;
-	std::vector<std::string> xtrainfo;
-	std::vector<std::string> restypes;
-	std::vector<std::pair<std::string,std::string> > mines; //first - name; second - event description
 };
 
 

+ 22 - 1
lib/Connection.cpp

@@ -146,7 +146,7 @@ void CConnection::close()
 }
 
 CSaveFile::CSaveFile( const std::string &fname )
-	:sfile(new std::ofstream(fname.c_str()))
+	:sfile(new std::ofstream(fname.c_str(),std::ios::binary))
 {
 	if(!(*sfile))
 	{
@@ -164,4 +164,25 @@ int CSaveFile::write( const void * data, unsigned size )
 {
 	sfile->write((char *)data,size);
 	return size;
+}
+
+CLoadFile::CLoadFile( const std::string &fname )
+:sfile(new std::ifstream(fname.c_str(),std::ios::binary))
+{
+	if(!(*sfile))
+	{
+		tlog1 << "Error: cannot open to read " << fname << std::endl;
+		sfile = NULL;
+	}
+}
+
+CLoadFile::~CLoadFile()
+{
+	delete sfile;
+}
+
+int CLoadFile::read( const void * data, unsigned size )
+{
+	sfile->read((char *)data,size);
+	return size;
 }

+ 32 - 18
lib/Connection.h

@@ -185,7 +185,10 @@ public:
 	template <typename T>
 	void savePointer(const T &data)
 	{
-		*this << *data;
+		ui8 hlp = (data!=NULL);
+		*this << hlp;
+		if(hlp)
+			*this << *data;
 	}
 	template <typename T>
 	void save(const T &data)
@@ -231,15 +234,8 @@ public:
 	}
 	void saveSerializable(const std::string &data)
 	{
-		if(!data.length())
-		{
-			*this << ui8(0);
-		}
-		else
-		{
-			*this << ui32(data.length());
-			this->This()->write(data.c_str(),data.size());
-		}
+		*this << ui32(data.length());
+		this->This()->write(data.c_str(),data.size());
 	}
 	template <typename T1, typename T2>
 	void saveSerializable(const std::pair<T1,T2> &data)
@@ -311,6 +307,14 @@ public:
 	template <typename T>
 	void loadPointer(T &data)
 	{
+		ui8 hlp;
+		*this >> hlp;
+		if(!hlp)
+		{
+			data = NULL;
+			return;
+		}
+
 		tlog5<<"Allocating memory for pointer!"<<std::endl;
 		typedef typename boost::remove_pointer<T>::type npT;
 		data = new npT;
@@ -357,14 +361,10 @@ public:
 	}
 	void loadSerializable(std::string &data)
 	{
-		ui8 length[4];
-		*this >> length[0];
-		if(!length[0]) return;
-		*this >> length[1];
-		*this >> length[2];
-		*this >> length[3];
-		data.resize(*((ui32*)length));
-		this->This()->read((void*)data.c_str(),*((ui32*)length));
+		ui32 length;
+		*this >> length;
+		data.resize(length);
+		this->This()->read((void*)data.c_str(),length);
 	}
 
 };
@@ -384,6 +384,20 @@ public:
 	int write(const void * data, unsigned size);
 };
 
+class DLL_EXPORT CLoadFile
+	: public CISer<CLoadFile>
+{
+	void dummyMagicFunction()
+	{
+		*this >> std::string("This function makes stuff working.");
+	}
+public:
+	std::ifstream *sfile;
+	CLoadFile(const std::string &fname);
+	~CLoadFile();
+	int read(const void * data, unsigned size);
+};
+
 class DLL_EXPORT CConnection
 	:public CISer<CConnection>, public COSer<CConnection>
 {

+ 192 - 433
map.cpp

@@ -206,37 +206,54 @@ CCreatureSet readCreatureSet(unsigned char * bufor, int &i, int number, bool ver
 }
 CMapHeader::CMapHeader(unsigned char *map)
 {
-	this->version = (Eformat)map[0]; //wersja mapy
-	this->areAnyPLayers = map[4]; //seems to be invalid
-	this->height = this->width = map[5]; // wymiary mapy
-	this->twoLevel = map[9]; //czy sa lochy
-
-	int length = map[10]; //name length
-	int i=14, pom;
-	while (i-14<length)	//read name
-		this->name+=map[i++];
-	length = map[i] + map[i+1]*256; //description length
-	i+=4;
-	for (pom=0;pom<length;pom++)
-		this->description+=map[i++];
-	this->difficulty = map[i++]; // reading map difficulty
-	if(version!=RoE)
-	{
-		this->levelLimit = map[i++]; // hero level limit
-	}
+	int i=0;
+	initFromMemory(map,i);
+}
+
+CMapHeader::CMapHeader()
+{
+	areAnyPLayers = difficulty = levelLimit = howManyTeams = 0;
+	height = width = twoLevel = -1;
+}
+
+void CMapHeader::initFromMemory( unsigned char *bufor, int &i )
+{
+	version = (Eformat)(readNormalNr(bufor,i)); i+=4; //map version
+	areAnyPLayers = readChar(bufor,i); //invalid on some maps
+	height = width = (readNormalNr(bufor,i)); i+=4; // wymiary mapy
+	twoLevel = readChar(bufor,i); //czy sa lochy
+	int pom;
+	name = readString(bufor,i);
+	description= readString(bufor,i);
+	difficulty = readChar(bufor,i); // reading map difficulty
+	if(version != RoE)
+		levelLimit = readChar(bufor,i); // hero level limit
 	else
-	{
 		levelLimit = 0;
+	loadPlayerInfo(pom, bufor, i);
+	loadViCLossConditions(bufor, i);
+
+	howManyTeams=bufor[i++]; //read number of teams
+	if(howManyTeams>0) //read team numbers
+	{
+		for(int rr=0; rr<8; ++rr)
+		{
+			players[rr].team=bufor[i++];
+		}
 	}
+}
+void CMapHeader::loadPlayerInfo( int &pom, unsigned char * bufor, int &i )
+{
 	for (pom=0;pom<8;pom++)
 	{
-		this->players[pom].canHumanPlay = map[i++];
-		this->players[pom].canComputerPlay = map[i++];
-		if ((!(this->players[pom].canHumanPlay || this->players[pom].canComputerPlay)))
+		players[pom].canHumanPlay = bufor[i++];
+		players[pom].canComputerPlay = bufor[i++];
+		if ((!(players[pom].canHumanPlay || players[pom].canComputerPlay)))
 		{
+			memset(&players[pom],0,sizeof(PlayerInfo));
 			switch(version)
 			{
-			case SoD: case WoG:
+			case SoD: case WoG: 
 				i+=13;
 				break;
 			case AB:
@@ -249,204 +266,186 @@ CMapHeader::CMapHeader(unsigned char *map)
 			continue;
 		}
 
-		this->players[pom].AITactic = map[i++];
+		players[pom].AITactic = bufor[i++];
 
 		if(version == SoD || version == WoG)
-			i++;
+			players[pom].p7= bufor[i++];
+		else
+			players[pom].p7= -1;
 
-		this->players[pom].allowedFactions = 0;
-		this->players[pom].allowedFactions += map[i++];
+		players[pom].allowedFactions = 0;
+		players[pom].allowedFactions += bufor[i++];
 		if(version != RoE)
-			this->players[pom].allowedFactions += (map[i++])*256;
+			players[pom].allowedFactions += (bufor[i++])*256;
 
-		this->players[pom].isFactionRandom = map[i++];
-		this->players[pom].hasMainTown = map[i++];
-		if (this->players[pom].hasMainTown)
+		players[pom].isFactionRandom = bufor[i++];
+		players[pom].hasMainTown = bufor[i++];
+		if (players[pom].hasMainTown)
 		{
 			if(version != RoE)
 			{
-				this->players[pom].generateHeroAtMainTown = map[i++];
-				this->players[pom].generateHero = map[i++];
+				players[pom].generateHeroAtMainTown = bufor[i++];
+				players[pom].generateHero = bufor[i++];
+			}
+			else
+			{
+				players[pom].generateHeroAtMainTown = false;
+				players[pom].generateHero = false;
 			}
-			this->players[pom].posOfMainTown.x = map[i++];
-			this->players[pom].posOfMainTown.y = map[i++];
-			this->players[pom].posOfMainTown.z = map[i++];
+
+			players[pom].posOfMainTown.x = bufor[i++];
+			players[pom].posOfMainTown.y = bufor[i++];
+			players[pom].posOfMainTown.z = bufor[i++];
+
+
 		}
-		players[pom].p8= map[i++];
-		players[pom].p9= map[i++];
+		players[pom].p8= bufor[i++];
+		players[pom].p9= bufor[i++];		
 		if(players[pom].p9!=0xff)
 		{
-			players[pom].mainHeroPortrait = map[i++];
-			int nameLength = map[i++];
-			i+=3;
+			players[pom].mainHeroPortrait = bufor[i++];
+			int nameLength = bufor[i++];
+			i+=3; 
 			for (int pp=0;pp<nameLength;pp++)
-				players[pom].mainHeroName+=map[i++];
+				players[pom].mainHeroName+=bufor[i++];
 		}
 
-		if(version!=RoE)
+		if(version != RoE)
 		{
-			i++; ////heroes placeholders //domostwa
-			int heroCount = map[i++];
+			i++; ////unknown byte
+			int heroCount = bufor[i++];
 			i+=3;
 			for (int pp=0;pp<heroCount;pp++)
 			{
 				SheroName vv;
-				vv.heroID=map[i++];
-				int hnl = map[i++];
+				vv.heroID=bufor[i++];
+				int hnl = bufor[i++];
 				i+=3;
 				for (int zz=0;zz<hnl;zz++)
 				{
-					vv.heroName+=map[i++];
+					vv.heroName+=bufor[i++];
 				}
-				this->players[pom].heroesNames.push_back(vv);
+				players[pom].heroesNames.push_back(vv);
 			}
 		}
 	}
-	this->victoryCondition = (EvictoryConditions)map[i++];
-	if (this->victoryCondition != winStandard) //specific victory conditions
+}
+
+void CMapHeader::loadViCLossConditions( unsigned char * bufor, int &i)
+{
+	victoryCondition.condition = (EvictoryConditions)bufor[i++];
+	if (victoryCondition.condition != winStandard) //specific victory conditions
 	{
 		int nr;
-		switch (this->victoryCondition) //read victory conditions
+		switch (victoryCondition.condition) //read victory conditions
 		{
 		case artifact:
 			{
-				this->vicConDetails = new VicCon0();
-				((VicCon0*)this->vicConDetails)->ArtifactID = map[i+2];
+				victoryCondition.ID = bufor[i+2];
 				nr=(version==RoE ? 1 : 2);
 				break;
 			}
 		case gatherTroop:
 			{
-				this->vicConDetails = new VicCon1();
-				int temp1 = map[i+2];
-				int temp2 = map[i+3];
-				((VicCon1*)this->vicConDetails)->monsterID = map[i+2];
-				((VicCon1*)this->vicConDetails)->neededQuantity=readNormalNr(map, i+(version==RoE ? 3 : 4));
+				int temp1 = bufor[i+2];
+				int temp2 = bufor[i+3];
+				victoryCondition.ID = bufor[i+2];
+				victoryCondition.count = readNormalNr(bufor, i+(version==RoE ? 3 : 4));
 				nr=(version==RoE ? 5 : 6);
 				break;
 			}
 		case gatherResource:
 			{
-				this->vicConDetails = new VicCon2();
-				((VicCon2*)this->vicConDetails)->resourceID = map[i+2];
-				((VicCon2*)this->vicConDetails)->neededQuantity=readNormalNr(map, i+3);
+				victoryCondition.ID = bufor[i+2];
+				victoryCondition.count = readNormalNr(bufor, i+3);
 				nr=5;
 				break;
 			}
 		case buildCity:
 			{
-				this->vicConDetails = new VicCon3();
-				((VicCon3*)this->vicConDetails)->posOfCity.x = map[i+2];
-				((VicCon3*)this->vicConDetails)->posOfCity.y = map[i+3];
-				((VicCon3*)this->vicConDetails)->posOfCity.z = map[i+4];
-				((VicCon3*)this->vicConDetails)->councilNeededLevel = map[i+5];
-				((VicCon3*)this->vicConDetails)->fortNeededLevel = map[i+6];
+				victoryCondition.pos.x = bufor[i+2];
+				victoryCondition.pos.y = bufor[i+3];
+				victoryCondition.pos.z = bufor[i+4];
+				victoryCondition.count = bufor[i+5];
+				victoryCondition.ID = bufor[i+6];
 				nr=5;
 				break;
 			}
 		case buildGrail:
 			{
-				this->vicConDetails = new VicCon4();
-				if (map[i+4]>2)
-					((VicCon4*)this->vicConDetails)->anyLocation = true;
+				if (bufor[i+4]>2)
+					victoryCondition.pos = int3(-1,-1,-1);
 				else
 				{
-					((VicCon4*)this->vicConDetails)->whereBuildGrail.x = map[i+2];
-					((VicCon4*)this->vicConDetails)->whereBuildGrail.y = map[i+3];
-					((VicCon4*)this->vicConDetails)->whereBuildGrail.z = map[i+4];
+					victoryCondition.pos.x = bufor[i+2];
+					victoryCondition.pos.y = bufor[i+3];
+					victoryCondition.pos.z = bufor[i+4];
 				}
 				nr=3;
 				break;
 			}
 		case beatHero:
-			{
-				this->vicConDetails = new VicCon5();
-				((VicCon5*)this->vicConDetails)->locationOfHero.x = map[i+2];
-				((VicCon5*)this->vicConDetails)->locationOfHero.y = map[i+3];
-				((VicCon5*)this->vicConDetails)->locationOfHero.z = map[i+4];
-				nr=3;
-				break;
-			}
 		case captureCity:
-			{
-				this->vicConDetails = new VicCon6();
-				((VicCon6*)this->vicConDetails)->locationOfTown.x = map[i+2];
-				((VicCon6*)this->vicConDetails)->locationOfTown.y = map[i+3];
-				((VicCon6*)this->vicConDetails)->locationOfTown.z = map[i+4];
-				nr=3;
-				break;
-			}
 		case beatMonster:
 			{
-				this->vicConDetails = new VicCon7();
-				((VicCon7*)this->vicConDetails)->locationOfMonster.x = map[i+2];
-				((VicCon7*)this->vicConDetails)->locationOfMonster.y = map[i+3];
-				((VicCon7*)this->vicConDetails)->locationOfMonster.z = map[i+4];
+				victoryCondition.pos.x = bufor[i+2];
+				victoryCondition.pos.y = bufor[i+3];
+				victoryCondition.pos.z = bufor[i+4];
 				nr=3;
 				break;
 			}
 		case takeDwellings:
-			{
-				this->vicConDetails = new CspecificVictoryConidtions();
-				nr=3;
-				break;
-			}
 		case takeMines:
 			{
-				this->vicConDetails = new CspecificVictoryConidtions();
 				nr=3;
 				break;
 			}
 		case transportItem:
 			{
-				this->vicConDetails = new VicCona();
-				((VicCona*)this->vicConDetails)->artifactID =  map[i+2];
-				((VicCona*)this->vicConDetails)->destinationPlace.x = map[i+3];
-				((VicCona*)this->vicConDetails)->destinationPlace.y = map[i+4];
-				((VicCona*)this->vicConDetails)->destinationPlace.z = map[i+5];
+				victoryCondition.ID =  bufor[i+2];
+				victoryCondition.pos.x = bufor[i+3];
+				victoryCondition.pos.y = bufor[i+4];
+				victoryCondition.pos.z = bufor[i+5];
 				nr=4;
 				break;
 			}
 		}
-		this->vicConDetails->allowNormalVictory = map[i++];
-		this->vicConDetails->appliesToAI = map[i++];
+		victoryCondition.allowNormalVictory = bufor[i++];
+		victoryCondition.appliesToAI = bufor[i++];
 		i+=nr;
 	}
-	this->lossCondition.typeOfLossCon = (ElossCon)map[i++];
-	switch (this->lossCondition.typeOfLossCon) //read loss conditions
+	lossCondition.typeOfLossCon = (ElossCon)bufor[i++];
+	switch (lossCondition.typeOfLossCon) //read loss conditions
 	{
 	case lossCastle:
-		  {
-			  this->lossCondition.castlePos.x=map[i++];
-			  this->lossCondition.castlePos.y=map[i++];
-			  this->lossCondition.castlePos.z=map[i++];
-		  }
+		{
+			lossCondition.castlePos.x=bufor[i++];
+			lossCondition.castlePos.y=bufor[i++];
+			lossCondition.castlePos.z=bufor[i++];
+			break;
+		}
 	case lossHero:
-		  {
-			  this->lossCondition.heroPos.x=map[i++];
-			  this->lossCondition.heroPos.y=map[i++];
-			  this->lossCondition.heroPos.z=map[i++];
-		  }
-	case timeExpires:
 		{
-			this->lossCondition.timeLimit = readNormalNr(map, i++,2);
-			i++;
+			lossCondition.heroPos.x=bufor[i++];
+			lossCondition.heroPos.y=bufor[i++];
+			lossCondition.heroPos.z=bufor[i++];
+			break;
 		}
-	}
-	this->howManyTeams=map[i++]; //read number of teams
-	if(this->howManyTeams>0) //read team numbers
-	{
-		for(int rr=0; rr<8; ++rr)
+	case timeExpires:
 		{
-			this->players[rr].team=map[i++];
+			lossCondition.timeLimit = readNormalNr(bufor,i++,2);
+			i++;
+			break;
 		}
 	}
 }
+
 void Mapa::initFromBytes(unsigned char * bufor)
 {
+	int i=0;
+	initFromMemory(bufor,i);
 	timeHandler th;
 	th.getDif();
-	int i=0;
 	readHeader(bufor, i);
 	tlog0<<"\tReading header: "<<th.getDif()<<std::endl;
 
@@ -555,6 +554,10 @@ Mapa::Mapa(std::string filename)
 	initFromBytes(initTable);
 }
 
+Mapa::Mapa()
+{
+
+}
 CGHeroInstance * Mapa::getHero(int ID, int mode)
 {
 	if (mode != 0)
@@ -602,64 +605,64 @@ int Mapa::loadSeerHut( unsigned char * bufor, int i, CGObjectInstance *& nobj )
 		{
 		case 1:
 			{
-				hut->r1exp = readNormalNr(bufor,i); i+=4;
+				hut->rVal = readNormalNr(bufor,i); i+=4;
 				break;
 			}
 		case 2:
 			{
-				hut->r2mana = readNormalNr(bufor,i); i+=4;
+				hut->rVal = readNormalNr(bufor,i); i+=4;
 				break;
 			}
 		case 3:
 			{
-				hut->r3morale = bufor[i]; ++i;
+				hut->rVal = bufor[i]; ++i;
 				break;
 			}
 		case 4:
 			{
-				hut->r4luck = bufor[i]; ++i;
+				hut->rVal = bufor[i]; ++i;
 				break;
 			}
 		case 5:
 			{
-				hut->r5type = bufor[i]; ++i;
-				hut->r5amount = readNormalNr(bufor,i, 3); i+=3;
+				hut->rID = bufor[i]; ++i;
+				hut->rVal = readNormalNr(bufor,i, 3); i+=3;
 				i+=1;
 				break;
 			}
 		case 6:
 			{
-				hut->r6type = bufor[i]; ++i;
-				hut->r6amount = bufor[i]; ++i;
+				hut->rID = bufor[i]; ++i;
+				hut->rVal = bufor[i]; ++i;
 				break;
 			}
 		case 7:
 			{
-				hut->r7ability = bufor[i]; ++i;
-				hut->r7level = bufor[i]; ++i;
+				hut->rID = bufor[i]; ++i;
+				hut->rVal = bufor[i]; ++i;
 				break;
 			}
 		case 8:
 			{
-				hut->r8art = readNormalNr(bufor,i, (version == RoE ? 1 : 2)); i+=(version == RoE ? 1 : 2);
+				hut->rID = readNormalNr(bufor,i, (version == RoE ? 1 : 2)); i+=(version == RoE ? 1 : 2);
 				break;
 			}
 		case 9:
 			{
-				hut->r9spell = bufor[i]; ++i;
+				hut->rID = bufor[i]; ++i;
 				break;
 			}
 		case 10:
 			{
 				if(version>RoE)
 				{
-					hut->r10creature = readNormalNr(bufor,i, 2); i+=2;
-					hut->r10amount = readNormalNr(bufor,i, 2); i+=2;
+					hut->rID = readNormalNr(bufor,i, 2); i+=2;
+					hut->rVal = readNormalNr(bufor,i, 2); i+=2;
 				}
 				else
 				{
-					hut->r10creature = bufor[i]; ++i;
-					hut->r10amount = readNormalNr(bufor,i, 2); i+=2;
+					hut->rID = bufor[i]; ++i;
+					hut->rVal = readNormalNr(bufor,i, 2); i+=2;
 				}
 				break;
 			}
@@ -975,233 +978,6 @@ void Mapa::loadHero( CGObjectInstance * &nobj, unsigned char * bufor, int &i )
 	nhi->movement = -1;
 }
 
-void Mapa::loadPlayerInfo( int &pom, unsigned char * bufor, int &i )
-{
-	for (pom=0;pom<8;pom++)
-	{
-		players[pom].canHumanPlay = bufor[i++];
-		players[pom].canComputerPlay = bufor[i++];
-		if ((!(players[pom].canHumanPlay || players[pom].canComputerPlay)))
-		{
-			memset(&players[pom],0,sizeof(PlayerInfo));
-			switch(version)
-			{
-			case SoD: case WoG: 
-				i+=13;
-				break;
-			case AB:
-				i+=12;
-				break;
-			case RoE:
-				i+=6;
-				break;
-			}
-			continue;
-		}
-
-		players[pom].AITactic = bufor[i++];
-
-		if(version == SoD || version == WoG)
-			players[pom].p7= bufor[i++];
-		else
-			players[pom].p7= -1;
-
-		players[pom].allowedFactions = 0;
-		players[pom].allowedFactions += bufor[i++];
-		if(version != RoE)
-			players[pom].allowedFactions += (bufor[i++])*256;
-
-		players[pom].isFactionRandom = bufor[i++];
-		players[pom].hasMainTown = bufor[i++];
-		if (players[pom].hasMainTown)
-		{
-			if(version != RoE)
-			{
-				players[pom].generateHeroAtMainTown = bufor[i++];
-				players[pom].generateHero = bufor[i++];
-			}
-			else
-			{
-				players[pom].generateHeroAtMainTown = false;
-				players[pom].generateHero = false;
-			}
-
-			players[pom].posOfMainTown.x = bufor[i++];
-			players[pom].posOfMainTown.y = bufor[i++];
-			players[pom].posOfMainTown.z = bufor[i++];
-
-
-		}
-		players[pom].p8= bufor[i++];
-		players[pom].p9= bufor[i++];		
-		if(players[pom].p9!=0xff)
-		{
-			players[pom].mainHeroPortrait = bufor[i++];
-			int nameLength = bufor[i++];
-			i+=3; 
-			for (int pp=0;pp<nameLength;pp++)
-				players[pom].mainHeroName+=bufor[i++];
-		}
-
-		if(version != RoE)
-		{
-			i++; ////unknown byte
-			int heroCount = bufor[i++];
-			i+=3;
-			for (int pp=0;pp<heroCount;pp++)
-			{
-				SheroName vv;
-				vv.heroID=bufor[i++];
-				int hnl = bufor[i++];
-				i+=3;
-				for (int zz=0;zz<hnl;zz++)
-				{
-					vv.heroName+=bufor[i++];
-				}
-				players[pom].heroesNames.push_back(vv);
-			}
-		}
-	}
-}
-
-void Mapa::loadViCLossConditions( unsigned char * bufor, int &i)
-{
-	victoryCondition = (EvictoryConditions)bufor[i++];
-	if (victoryCondition != winStandard) //specific victory conditions
-	{
-		int nr;
-		switch (victoryCondition) //read victory conditions
-		{
-		case artifact:
-			{
-				vicConDetails = new VicCon0();
-				((VicCon0*)vicConDetails)->ArtifactID = bufor[i+2];
-				nr=(version==RoE ? 1 : 2);
-				break;
-			}
-		case gatherTroop:
-			{
-				vicConDetails = new VicCon1();
-				int temp1 = bufor[i+2];
-				int temp2 = bufor[i+3];
-				((VicCon1*)vicConDetails)->monsterID = bufor[i+2];
-				((VicCon1*)vicConDetails)->neededQuantity=readNormalNr(bufor,i+(version==RoE ? 3 : 4));
-				nr=(version==RoE ? 5 : 6);
-				break;
-			}
-		case gatherResource:
-			{
-				vicConDetails = new VicCon2();
-				((VicCon2*)vicConDetails)->resourceID = bufor[i+2];
-				((VicCon2*)vicConDetails)->neededQuantity=readNormalNr(bufor,i+3);
-				nr=5;
-				break;
-			}
-		case buildCity:
-			{
-				vicConDetails = new VicCon3();
-				((VicCon3*)vicConDetails)->posOfCity.x = bufor[i+2];
-				((VicCon3*)vicConDetails)->posOfCity.y = bufor[i+3];
-				((VicCon3*)vicConDetails)->posOfCity.z = bufor[i+4];
-				((VicCon3*)vicConDetails)->councilNeededLevel = bufor[i+5];
-				((VicCon3*)vicConDetails)->fortNeededLevel = bufor[i+6];
-				nr=5;
-				break;
-			}
-		case buildGrail:
-			{
-				vicConDetails = new VicCon4();
-				if (bufor[i+4]>2)
-					((VicCon4*)vicConDetails)->anyLocation = true;
-				else
-				{
-					((VicCon4*)vicConDetails)->whereBuildGrail.x = bufor[i+2];
-					((VicCon4*)vicConDetails)->whereBuildGrail.y = bufor[i+3];
-					((VicCon4*)vicConDetails)->whereBuildGrail.z = bufor[i+4];
-				}
-				nr=3;
-				break;
-			}
-		case beatHero:
-			{
-				vicConDetails = new VicCon5();
-				((VicCon5*)vicConDetails)->locationOfHero.x = bufor[i+2];
-				((VicCon5*)vicConDetails)->locationOfHero.y = bufor[i+3];
-				((VicCon5*)vicConDetails)->locationOfHero.z = bufor[i+4];				
-				nr=3;
-				break;
-			}
-		case captureCity:
-			{
-				vicConDetails = new VicCon6();
-				((VicCon6*)vicConDetails)->locationOfTown.x = bufor[i+2];
-				((VicCon6*)vicConDetails)->locationOfTown.y = bufor[i+3];
-				((VicCon6*)vicConDetails)->locationOfTown.z = bufor[i+4];				
-				nr=3;
-				break;
-			}
-		case beatMonster:
-			{
-				vicConDetails = new VicCon7();
-				((VicCon7*)vicConDetails)->locationOfMonster.x = bufor[i+2];
-				((VicCon7*)vicConDetails)->locationOfMonster.y = bufor[i+3];
-				((VicCon7*)vicConDetails)->locationOfMonster.z = bufor[i+4];				
-				nr=3;
-				break;
-			}
-		case takeDwellings:
-			{		
-				vicConDetails = new CspecificVictoryConidtions();
-				nr=0;
-				break;
-			}
-		case takeMines:
-			{	
-				vicConDetails = new CspecificVictoryConidtions();	
-				nr=0;
-				break;
-			}
-		case transportItem:
-			{
-				vicConDetails = new VicCona();
-				((VicCona*)vicConDetails)->artifactID =  bufor[i+2];
-				((VicCona*)vicConDetails)->destinationPlace.x = bufor[i+3];
-				((VicCona*)vicConDetails)->destinationPlace.y = bufor[i+4];
-				((VicCona*)vicConDetails)->destinationPlace.z = bufor[i+5];				
-				nr=4;
-				break;
-			}
-		}
-		vicConDetails->allowNormalVictory = bufor[i++];
-		vicConDetails->appliesToAI = bufor[i++];
-		i+=nr;
-	}
-	lossCondition.typeOfLossCon = (ElossCon)bufor[i++];
-	switch (lossCondition.typeOfLossCon) //read loss conditions
-	{
-	case lossCastle:
-		{
-			lossCondition.castlePos.x=bufor[i++];
-			lossCondition.castlePos.y=bufor[i++];
-			lossCondition.castlePos.z=bufor[i++];
-			break;
-		}
-	case lossHero:
-		{
-			lossCondition.heroPos.x=bufor[i++];
-			lossCondition.heroPos.y=bufor[i++];
-			lossCondition.heroPos.z=bufor[i++];
-			break;
-		}
-	case timeExpires:
-		{
-			lossCondition.timeLimit = readNormalNr(bufor,i++,2);
-			i++;
-			break;
-		}
-	}
-}
-
 void Mapa::readRumors( unsigned char * bufor, int &i)
 {
 	int rumNr = readNormalNr(bufor,i,4);i+=4;
@@ -1220,36 +996,6 @@ void Mapa::readRumors( unsigned char * bufor, int &i)
 
 void Mapa::readHeader( unsigned char * bufor, int &i)
 {
-	version = (Eformat)(readNormalNr(bufor,i)); i+=4; //map version
-	areAnyPLayers = readChar(bufor,i); //invalid on some maps
-	height = width = (readNormalNr(bufor,i)); i+=4; // wymiary mapy
-	twoLevel = readChar(bufor,i); //czy sa lochy
-	terrain = new TerrainTile**[width]; // allocate memory 
-	for (int ii=0;ii<width;ii++)
-	{
-		terrain[ii] = new TerrainTile*[height]; // allocate memory 
-		for(int jj=0;jj<height;jj++)
-			terrain[ii][jj] = new TerrainTile[twoLevel+1];
-	}
-	int pom;
-	name = readString(bufor,i);
-	description= readString(bufor,i);
-	difficulty = readChar(bufor,i); // reading map difficulty
-	if(version != RoE)
-		levelLimit = readChar(bufor,i); // hero level limit
-	else
-		levelLimit = 0;
-	loadPlayerInfo(pom, bufor, i);
-	loadViCLossConditions(bufor, i);
-
-	howManyTeams=bufor[i++]; //read number of teams
-	if(howManyTeams>0) //read team numbers
-	{
-		for(int rr=0; rr<8; ++rr)
-		{
-			players[rr].team=bufor[i++];
-		}
-	}
 	//reading allowed heroes (20 bytes)
 	int ist;
 
@@ -1467,6 +1213,14 @@ void Mapa::readPredefinedHeroes( unsigned char * bufor, int &i)
 
 void Mapa::readTerrain( unsigned char * bufor, int &i)
 {
+	terrain = new TerrainTile**[width]; // allocate memory 
+	for (int ii=0;ii<width;ii++)
+	{
+		terrain[ii] = new TerrainTile*[height]; // allocate memory 
+		for(int jj=0;jj<height;jj++)
+			terrain[ii][jj] = new TerrainTile[twoLevel+1];
+	}
+
 	for (int c=0; c<width; c++) // reading terrain
 	{
 		for (int z=0; z<height; z++)
@@ -1577,40 +1331,37 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
 					int messLong = readNormalNr(bufor,i, 4); i+=4;
 					if(messLong>0)
 					{
-						evnt->isMessage = true;
 						for(int yy=0; yy<messLong; ++yy)
 						{
 							evnt->message +=bufor[i+yy];
 						}
 						i+=messLong;
 					}
-					evnt->areGuarders = bufor[i]; ++i;
-					if(evnt->areGuarders)
+					if(bufor[i++])
 					{
 						evnt->guarders = readCreatureSet(bufor,i,7,(version>RoE)); 
 					}
 					i+=4;
 				}
-				else
-				{
-					evnt->isMessage = false;
-					evnt->areGuarders = false;
-				}
 				evnt->gainedExp = readNormalNr(bufor,i, 4); i+=4;
 				evnt->manaDiff = readNormalNr(bufor,i, 4); i+=4;
 				evnt->moraleDiff = readNormalNr(bufor,i, 1, true); ++i;
 				evnt->luckDiff = readNormalNr(bufor,i, 1, true); ++i;
-				evnt->wood = readNormalNr(bufor,i); i+=4;
-				evnt->mercury = readNormalNr(bufor,i); i+=4;
-				evnt->ore = readNormalNr(bufor,i); i+=4;
-				evnt->sulfur = readNormalNr(bufor,i); i+=4;
-				evnt->crystal = readNormalNr(bufor,i); i+=4;
-				evnt->gems = readNormalNr(bufor,i); i+=4;
-				evnt->gold = readNormalNr(bufor,i); i+=4;
-				evnt->attack = readNormalNr(bufor,i, 1); ++i;
-				evnt->defence = readNormalNr(bufor,i, 1); ++i;
-				evnt->power = readNormalNr(bufor,i, 1); ++i;
-				evnt->knowledge = readNormalNr(bufor,i, 1); ++i;
+
+				evnt->resources.resize(RESOURCE_QUANTITY);
+				for(int x=0; x<7; x++)
+				{
+					evnt->resources[x] = readNormalNr(bufor,i); 
+					i+=4;
+				}
+
+				evnt->primskills.resize(PRIMARY_SKILLS);
+				for(int x=0; x<4; x++)
+				{
+					evnt->primskills[x] = readNormalNr(bufor,i, 1); 
+					i++;
+				}
+
 				int gabn; //number of gained abilities
 				gabn = readNormalNr(bufor,i, 1); ++i;
 				for(int oo = 0; oo<gabn; ++oo)
@@ -1618,18 +1369,22 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
 					evnt->abilities.push_back(readNormalNr(bufor,i, 1)); ++i;
 					evnt->abilityLevels.push_back(readNormalNr(bufor,i, 1)); ++i;
 				}
+
 				int gart = readNormalNr(bufor,i, 1); ++i; //number of gained artifacts
 				for(int oo = 0; oo<gart; ++oo)
 				{
 					evnt->artifacts.push_back(readNormalNr(bufor,i, (version == RoE ? 1 : 2))); i+=(version == RoE ? 1 : 2);
 				}
+
 				int gspel = readNormalNr(bufor,i, 1); ++i; //number of gained spells
 				for(int oo = 0; oo<gspel; ++oo)
 				{
 					evnt->spells.push_back(readNormalNr(bufor,i, 1)); ++i;
 				}
+
 				int gcre = readNormalNr(bufor,i, 1); ++i; //number of gained creatures
 				evnt->creatures = readCreatureSet(bufor,i,gcre,(version>RoE));
+
 				i+=8;
 				evnt->availableFor = readNormalNr(bufor,i, 1); ++i;
 				evnt->computerActivate = readNormalNr(bufor,i, 1); ++i;
@@ -1886,18 +1641,22 @@ void Mapa::readObjects( unsigned char * bufor, int &i)
 				box->gainedExp = readNormalNr(bufor,i, 4); i+=4;
 				box->manaDiff = readNormalNr(bufor,i, 4); i+=4;
 				box->moraleDiff = readNormalNr(bufor,i, 1, true); ++i;
-				box->luckDiff = readNormalNr(bufor,i, 1, true); ++i;
-				box->wood = readNormalNr(bufor,i); i+=4;
-				box->mercury = readNormalNr(bufor,i); i+=4;
-				box->ore = readNormalNr(bufor,i); i+=4;
-				box->sulfur = readNormalNr(bufor,i); i+=4;
-				box->crystal = readNormalNr(bufor,i); i+=4;
-				box->gems = readNormalNr(bufor,i); i+=4;
-				box->gold = readNormalNr(bufor,i); i+=4;
-				box->attack = readNormalNr(bufor,i, 1); ++i;
-				box->defence = readNormalNr(bufor,i, 1); ++i;
-				box->power = readNormalNr(bufor,i, 1); ++i;
-				box->knowledge = readNormalNr(bufor,i, 1); ++i;
+				box->luckDiff = readNormalNr(bufor,i, 1, true); ++i;				
+				
+				box->resources.resize(RESOURCE_QUANTITY);
+				for(int x=0; x<7; x++)
+				{
+					box->resources[x] = readNormalNr(bufor,i); 
+					i+=4;
+				}
+
+				box->primskills.resize(PRIMARY_SKILLS);
+				for(int x=0; x<4; x++)
+				{
+					box->primskills[x] = readNormalNr(bufor,i, 1); 
+					i++;
+				}
+
 				int gabn; //number of gained abilities
 				gabn = readNormalNr(bufor,i, 1); ++i;
 				for(int oo = 0; oo<gabn; ++oo)

+ 211 - 78
map.h

@@ -84,6 +84,12 @@ struct DLL_EXPORT TerrainTile
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & tertype & terview & nuine & rivDir & malle &roadDir & siodmyTajemniczyBajt;
+
+		if(!h.saving)
+		{
+			visitable = blocked = false;
+			//these flags (and obj vectors) will be restored in map serialization
+		}
 	}
 };
 struct DLL_EXPORT SheroName //name of starting hero
@@ -132,53 +138,22 @@ struct DLL_EXPORT LossCondition
 		h & typeOfLossCon & castlePos & heroPos & timeLimit;
 	}
 };
-struct DLL_EXPORT CspecificVictoryConidtions
-{
-	bool allowNormalVictory;
-	bool appliesToAI;
-};
-struct DLL_EXPORT VicCon0 : public CspecificVictoryConidtions //acquire artifact
-{
-	int ArtifactID;
-};
-struct DLL_EXPORT VicCon1 : public CspecificVictoryConidtions //accumulate creatures
-{
-	int monsterID;
-	int neededQuantity;
-};
-struct DLL_EXPORT VicCon2 : public CspecificVictoryConidtions // accumulate resources
-{
-	int resourceID;
-	int neededQuantity;
-};
-struct DLL_EXPORT VicCon3 : public CspecificVictoryConidtions // upgrade specific town
-{
-	int3 posOfCity;
-	int councilNeededLevel; //0 - town; 1 - city; 2 - capitol
-	int fortNeededLevel;// 0 - fort; 1 - citadel; 2 - castle
-};
-struct DLL_EXPORT VicCon4 : public CspecificVictoryConidtions // build grail structure
-{
-	bool anyLocation;
-	int3 whereBuildGrail;
-};
-struct DLL_EXPORT VicCon5 : public CspecificVictoryConidtions // defeat a specific hero
-{
-	int3 locationOfHero;
-};
-struct DLL_EXPORT VicCon6 : public CspecificVictoryConidtions // capture a specific town
-{
-	int3 locationOfTown;
-};
-struct DLL_EXPORT VicCon7 : public CspecificVictoryConidtions // defeat a specific monster
-{
-	int3 locationOfMonster;
-};
-struct DLL_EXPORT VicCona : public CspecificVictoryConidtions //transport specific artifact
+struct DLL_EXPORT CVictoryCondition
 {
-	int artifactID;
-	int3 destinationPlace;
+	EvictoryConditions condition; //ID of condition
+	ui8 allowNormalVictory, appliesToAI;
+
+	int3 pos; //pos of city to upgrade (3); pos of town to build grail, {-1,-1,-1} if not relevant (4); hero pos (5); town pos(6); monster pos (7); destination pos(8)
+	ui32 ID; //artifact ID (0); monster ID (1); resource ID (2); needed fort level in upgraded town (3); artifact ID (8)
+	ui32 count; //needed count for creatures (1) / resource (2); upgraded town hall level (3); 
+
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & condition & allowNormalVictory & appliesToAI & pos & ID & count;
+	}
 };
+
 struct DLL_EXPORT Rumor
 {
 	std::string name, text;
@@ -222,21 +197,24 @@ class DLL_EXPORT CMapHeader
 {
 public:
 	Eformat version; // version of map Eformat
-	bool areAnyPLayers; // if there are any playable players on map
-	int height, width;
-	bool twoLevel; // if map has underground level
+	ui8 areAnyPLayers; // if there are any playable players on map
+	si32 height, width, twoLevel; //sizes
 	std::string name;  //name of map
 	std::string description;  //and description
-	int difficulty; // 0 easy - 4 impossible
-	int levelLimit;
+	ui8 difficulty; // 0 easy - 4 impossible
+	ui8 levelLimit;
 	LossCondition lossCondition;
-	EvictoryConditions victoryCondition; //victory conditions
-	CspecificVictoryConidtions * vicConDetails; // used only if vistory conditions aren't standard
+	CVictoryCondition victoryCondition; //victory conditions
 	PlayerInfo players[8]; // info about players
-	std::vector<int> teams;  // teams[i] = team of player no i
-	int howManyTeams;
+	std::vector<ui8> teams;  // teams[i] = team of player no i
+	ui8 howManyTeams;
+	void initFromMemory(unsigned char *bufor, int &i);
+	void loadViCLossConditions( unsigned char * bufor, int &i);
+	void loadPlayerInfo( int &pom, unsigned char * bufor, int &i);
 	CMapHeader(unsigned char *map); //an argument is a reference to string described a map (unpacked)
+	CMapHeader();
 };
+
 class DLL_EXPORT CMapInfo : public CMapHeader
 {
 public:
@@ -287,7 +265,7 @@ public:
 			return (a.width<b.width);
 			break;
 		case _viccon:
-			return (a.victoryCondition<b.victoryCondition);
+			return (a.victoryCondition.condition < b.victoryCondition.condition);
 			break;
 		case _name:
 			return (a.name<b.name);
@@ -299,29 +277,14 @@ public:
 	};
 	mapSorter(ESortBy es):sortBy(es){};
 };
-struct DLL_EXPORT Mapa
+struct DLL_EXPORT Mapa : public CMapHeader
 {
-	Eformat version; // version of map Eformat
 	ui32 checksum;
-	ui32 twoLevel; // if map has underground level
-	ui8 difficulty; // 0 easy - 4 impossible
-	ui8 levelLimit;
-	ui8 areAnyPLayers; // if there are any playable players on map
-	std::string name;  //name of map
-	std::string description;  //and description
-	ui32 height, width; 
 	TerrainTile*** terrain; 
 	std::vector<Rumor> rumors;
 	std::vector<DisposedHero> disposedHeroes;
 	std::vector<CGHeroInstance*> predefinedHeroes;
 	std::vector<CGDefInfo *> defy; // list of .def files with definitions from .h3m (may be custom)
-	std::set<CGDefInfo *> defs; // other defInfos - for randomized objects, objects added or modified by scripts
-	PlayerInfo players[8]; // info about players
-	std::vector<ui8> teams;  // teams[i] = team of player no i 
-	LossCondition lossCondition;
-	EvictoryConditions victoryCondition; //victory conditions
-	CspecificVictoryConidtions * vicConDetails; // used only if vistory conditions aren't standard
-	ui8 howManyTeams;
 	std::vector<ui8> allowedSpell; //allowedSpell[spell_ID] - if the spell is allowed
 	std::vector<ui8> allowedArtifact; //allowedArtifact[artifact_ID] - if the artifact is allowed
 	std::vector<ui8> allowedAbilities; //allowedAbilities[ability_ID] - if the ability is allowed
@@ -345,8 +308,6 @@ struct DLL_EXPORT Mapa
 	void readPredefinedHeroes( unsigned char * bufor, int &i);
 	void readHeader( unsigned char * bufor, int &i);
 	void readRumors( unsigned char * bufor, int &i);
-	void loadViCLossConditions( unsigned char * bufor, int &i);
-	void loadPlayerInfo( int &pom, unsigned char * bufor, int &i);
 	void loadHero( CGObjectInstance * &nobj, unsigned char * bufor, int &i);
 	void loadTown( CGObjectInstance * &nobj, unsigned char * bufor, int &i);
 	int loadSeerHut( unsigned char * bufor, int i, CGObjectInstance *& nobj);
@@ -355,13 +316,20 @@ struct DLL_EXPORT Mapa
 	void addBlockVisTiles(CGObjectInstance * obj);
 	void removeBlockVisTiles(CGObjectInstance * obj);
 	Mapa(std::string filename); //creates map structure from .h3m file
+	Mapa();
 	CGHeroInstance * getHero(int ID, int mode=0);
 	bool isInTheMap(int3 pos);
-	template <typename Handler> void serialize(Handler &h, const int version)
+	template <typename TObject, typename Handler> void serializeObj(Handler &h, const int version, TObject ** obj)
 	{
-		h & version & name & description & width & height & twoLevel & difficulty & levelLimit & rumors & defy & defs
-			& players & teams & lossCondition & victoryCondition & howManyTeams & allowedSpell & allowedAbilities
-			& allowedArtifact &allowedHeroes & events & grailPos;
+		h & *obj;
+	}
+	template <typename Handler> void serialize(Handler &h, const int formatVersion)
+	{
+		h & version & name & description & width & height & twoLevel & difficulty & levelLimit & areAnyPLayers & rumors;
+		
+		h & players & teams & lossCondition & victoryCondition & howManyTeams & allowedSpell 
+			& allowedAbilities & allowedArtifact & allowedHeroes & events & grailPos;
+
 		//TODO: viccondetails
 		if(h.saving)
 		{
@@ -386,7 +354,172 @@ struct DLL_EXPORT Mapa
 					for (int k = 0; k <= twoLevel ; k++)
 						h & terrain[i][j][k];
 		}
-		//TODO: recreate blockvis maps
+
+		//definfos
+		std::vector<CGDefInfo*> defs;
+
+		if(h.saving) //create vector with all defs used on map
+		{
+			for(int i=0; i<objects.size(); i++)
+				objects[i]->defInfo->serial = -1; //set serial to serial -1 - indicates that def is not present in defs vector
+
+			for(int i=0; i<objects.size(); i++)
+			{
+				CGDefInfo *cur = objects[i]->defInfo;
+				if(cur->serial < 0)
+				{
+					cur->serial = defs.size();
+					defs.push_back(cur);
+				}
+			}
+		}
+
+		h & ((h.saving) ? defs : defy);
+
+		//objects
+		if(h.saving)
+		{
+			ui32 hlp = objects.size(); 
+			h & hlp;
+		}
+		else
+		{
+			ui32 hlp;
+			h & hlp;
+			objects.resize(hlp);
+		}
+
+		h & CGTeleport::objs;
+
+		for(int i=0; i<objects.size(); i++)
+		{
+			CGObjectInstance *&obj = objects[i];
+			ui32 hlp;
+			si32 shlp;
+			h & (h.saving ? (hlp=obj->ID) : hlp);
+			switch(hlp)
+			{
+				#define SERIALIZE(TYPE) (   serializeObj<TYPE>( h,version,(TYPE**) (&obj) )   )
+			case 34: case 70: case 62:
+				SERIALIZE(CGHeroInstance);
+				break;
+			case 98: case 77:
+				SERIALIZE(CGTownInstance);
+				break;
+			case 26: //for event objects
+				SERIALIZE(CGEvent);
+				break;
+			case 51: //Mercenary Camp
+			case 23: //Marletto Tower
+			case 61: // Star Axis
+			case 32: // Garden of Revelation
+			case 100: //Learning Stone
+			case 102: //Tree of Knowledge
+				SERIALIZE(CGVisitableOPH);
+				break;
+			case 55: //mystical garden
+			case 112://windmill
+			case 109://water wheel
+				SERIALIZE(CGVisitableOPW);
+				break;
+			case 43: //teleport
+			case 44: //teleport
+			case 45: //teleport
+			case 103://subterranean gate
+				SERIALIZE(CGTeleport);
+				break;
+			case 12: //campfire
+			case 101: //treasure chest
+				SERIALIZE(CGPickable);
+				break;
+			case 54:  //Monster 
+			case 71: case 72: case 73: case 74: case 75:	// Random Monster 1 - 4
+			case 162: case 163: case 164:	
+				SERIALIZE(CGCreature);
+				break;
+			case 59: case 91: //ocean bottle and sign
+				SERIALIZE(CGSignBottle);
+				break;
+			case 83: //seer's hut
+				SERIALIZE(CGSeerHut);
+				break;
+			case 113: //witch hut
+				SERIALIZE(CGWitchHut);
+				break;
+			case 81: //scholar
+				SERIALIZE(CGScholar);
+				break;
+			case 33: case 219: //garrison
+				SERIALIZE(CGGarrison);
+				break;
+			case 5: //artifact	
+			case 65: case 66: case 67: case 68: case 69: //random artifact
+			case 93: //spell scroll
+				SERIALIZE(CGArtifact);
+				break;
+			case 76: case 79: //random resource; resource
+				SERIALIZE(CGResource);
+				break;
+			case 53: 
+				SERIALIZE(CGMine);
+				break;
+			case 88: case 89: case 90: //spell shrine
+				SERIALIZE(CGShrine);
+				break;
+			case 6:
+				SERIALIZE(CGPandoraBox);
+				break;
+			case 217:
+			case 216:
+			case 218:
+				//TODO cregen
+				SERIALIZE(CGObjectInstance);
+				break;
+			case 215:
+				SERIALIZE(CGQuestGuard);
+				break;
+			default:
+				SERIALIZE(CGObjectInstance);
+			}
+
+#undef SERIALIZE
+
+			//definfo
+			h & (h.saving ? (shlp=obj->defInfo->serial) : shlp); //read / write pos of definfo in defs vector
+			if(!h.saving)
+				obj->defInfo = defy[shlp];
+		}
+
+		if(!h.saving)
+		{
+
+			for(int i=0; i<objects.size(); i++)
+			{
+				if(objects[i]->ID == 34)
+					heroes.push_back(static_cast<CGHeroInstance*>(objects[i]));
+				else if(objects[i]->ID == 98)
+					towns.push_back(static_cast<CGTownInstance*>(objects[i]));
+
+				addBlockVisTiles(objects[i]); //recreate blockvis map
+			}
+			for(int i=0; i<heroes.size(); i++) //if hero is visiting/garrisoned in town set appropriate pointers
+			{
+				int3 vistile = heroes[i]->pos; vistile.x++;
+				for(int j=0; j<towns.size(); j++)
+				{
+					if(vistile == towns[j]->pos) //hero stands on the town entrance
+					{
+						if(heroes[i]->inTownGarrison)
+							towns[j]->garrisonHero = heroes[i];
+						else
+							towns[j]->visitingHero = heroes[i];
+
+						heroes[i]->visitedTown = towns[j];
+					}
+				}
+			}
+
+		}
 	}
 };
 #endif // __MAP_H__

+ 10 - 3
mapHandler.cpp

@@ -445,14 +445,15 @@ void CMapHandler::init()
 		if(i<ccc)
 		{
 			n = CGI->state->villages[i];
-			map->defs.insert(CGI->state->forts[i]);
+			map->defy.push_back(CGI->state->forts[i]);
 		}
 		else 
 			n = CGI->state->capitols[i%ccc];
 		ifs >> n->name;
 		if(!n)
 			tlog1 << "*HUGE* Warning - missing town def for " << i << std::endl;
-		map->defs.insert(n);
+		else
+			map->defy.push_back(n);
 	} 
 	tlog0<<"\tLoading town def info: "<<th.getDif()<<std::endl;
 
@@ -464,8 +465,14 @@ void CMapHandler::init()
 		}
 	}
 
+	//for(int i=0; i<map->defy.size(); i++)
+	//{
+	//	map->defy[i]->serial = i;
+	//	processDef(map->defy[i]);
+	//}
+
 	std::for_each(map->defy.begin(),map->defy.end(),processDef); //load h3m defs
-	std::for_each(map->defs.begin(),map->defs.end(),processDef); //and non-h3m defs
+	//std::for_each(map->defs.begin(),map->defs.end(),processDef); //and non-h3m defs
 	tlog0<<"\tUnpacking and handling defs: "<<th.getDif()<<std::endl;
 
 	for(int i=0;i<PLAYER_LIMIT;i++)

+ 14 - 3
server/CGameHandler.cpp

@@ -409,10 +409,21 @@ void CGameHandler::handleConnection(std::set<int> players, CConnection &c)
 			case 98:
 				{
 					std::string fname;
+					Mapa * mapa;
 					c >> fname;
-					CSaveFile save(fname);
-					save << VLC->arth << VLC->buildh << VLC->creh << VLC->dobjinfo << VLC->heroh  
-						<< VLC->spellh << VLC->townh << this;
+
+					{
+						CSaveFile save(fname);
+						save << gs->map;
+					}
+
+					{
+						CLoadFile load(fname);
+						load >> mapa;
+					}
+					//save << VLC->arth << VLC->buildh << VLC->creh << VLC->dobjinfo << VLC->heroh  
+					//	<< VLC->spellh << VLC->townh << this;
+
 					//save << this;
 					break;
 				}