Selaa lähdekoodia

Further serialization code and refactorings.

Michał W. Urbańczyk 17 vuotta sitten
vanhempi
sitoutus
847a4f222c

+ 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;
 				}