瀏覽代碼

Serializer will now smartly send over network CArtifact* and CHero*. Unified handling of items stored in vector.

Started making support for Black Market / Artifact merchant.
Michał W. Urbańczyk 15 年之前
父節點
當前提交
ec6342d9a7

+ 3 - 3
client/CCastleInterface.cpp

@@ -798,7 +798,7 @@ void CCastleInterface::enterBlacksmith(int ArtifactID)
 		LOCPLINT->showInfoDialog(pom,std::vector<SComponent*>(), soundBase::sound_todo);
 		return;
 	}
-	int price = CGI->arth->artifacts[ArtifactID].price;
+	int price = CGI->arth->artifacts[ArtifactID]->price;
 	bool possible = (LOCPLINT->cb->getResourceAmount(6) >= price);
 	if(vstd::contains(hero->artifWorn,ui16(ArtifactID+9))) //hero already has machine
 		possible = false;
@@ -1218,7 +1218,7 @@ void CCastleInterface::CCreaInfo::clickRight(tribool down, bool previousState)
 				for(std::list<Bonus>::const_iterator i=ch->bonuses.begin(); i != ch->bonuses.end(); i++)
 					if(i->type == Bonus::CREATURE_GROWTH && i->subtype == level)
 						if (i->source == Bonus::ARTIFACT)
-							summ+=AddToString(CGI->arth->artifacts[i->id].Name()+" %+d",descr,i->val);
+							summ+=AddToString(CGI->arth->artifacts[i->id]->Name()+" %+d",descr,i->val);
 			};
 			ch = ci->town->visitingHero;
 		};
@@ -2056,7 +2056,7 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, int creMachineID, int aid, i
 	sprintf(pom,CGI->generaltexth->allTexts[274].c_str(),CGI->creh->creatures[creMachineID]->nameSing.c_str()); //build a new ...
 	printAtMiddle(pom,165,28,FONT_MEDIUM,tytulowy,bmp);
 	printAtMiddle(CGI->generaltexth->jktexts[43],165,218,FONT_MEDIUM,zwykly,bmp); //resource cost
-	SDL_itoa(CGI->arth->artifacts[aid].price,pom,10);
+	SDL_itoa(CGI->arth->artifacts[aid]->price,pom,10);
 	printAtMiddle(pom,165,290,FONT_MEDIUM,zwykly,bmp);
 
 	pos.w = bmp->w;

+ 3 - 3
client/CKingdomInterface.cpp

@@ -820,7 +820,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
 		else
 		{
 			artifacts[i]->text = CGI->generaltexth->artifDescriptions[artifacts[i]->type];
-			artifacts[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[artifacts[i]->type].Name());
+			artifacts[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[artifacts[i]->type]->Name());
 		}
 	}
 
@@ -832,7 +832,7 @@ void CKingdomInterface::CHeroItem::setHero(const CGHeroInstance * newHero)
 		else
 		{
 			backpack[i]->text = CGI->generaltexth->artifDescriptions[backpack[i]->type];
-			backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type].Name());
+			backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type]->Name());
 		}
 	}
 
@@ -883,7 +883,7 @@ void CKingdomInterface::CHeroItem::scrollArts(int move)
 		else
 		{
 			backpack[i]->text = CGI->generaltexth->artifDescriptions[backpack[i]->type];
-			backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type].Name());
+			backpack[i]->hoverText = boost::str(boost::format(CGI->generaltexth->heroscrn[1].c_str()) % CGI->arth->artifacts[backpack[i]->type]->Name());
 		}
 	}
 	showAll(screen2);

+ 2 - 2
client/CPlayerInterface.cpp

@@ -1109,13 +1109,13 @@ void CPlayerInterface::showGarrisonDialog( const CArmedInstance *up, const CGHer
  */
 void CPlayerInterface::showArtifactAssemblyDialog (ui32 artifactID, ui32 assembleTo, bool assemble, CFunctionList<void()> onYes, CFunctionList<void()> onNo)
 {
-	const CArtifact &artifact = CGI->arth->artifacts[artifactID];
+	const CArtifact &artifact = *CGI->arth->artifacts[artifactID];
 	std::string text = artifact.Description();
 	text += "\n\n";
 	std::vector<SComponent*> scs;
 
 	if (assemble) {
-		const CArtifact &assembledArtifact = CGI->arth->artifacts[assembleTo];
+		const CArtifact &assembledArtifact = *CGI->arth->artifacts[assembleTo];
 
 		// You possess all of the components to...
 		text += boost::str(boost::format(CGI->generaltexth->allTexts[732]) % assembledArtifact.Name());

+ 2 - 2
client/Client.cpp

@@ -281,7 +281,7 @@ void CClient::loadGame( const std::string & fname )
 	tlog0 <<"Waiting for server: "<<tmh.getDif()<<std::endl;
 
 	serv = new CConnection(conf.cc.server,portc,NAME);
-	serv->setGS(gs);
+	serv->addStdVecItems(gs);
 	tlog0 <<"Setting up connection: "<<tmh.getDif()<<std::endl;
 
 	ui8 pom8;
@@ -356,7 +356,6 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 	CGI->state = new CGameState();
 	tlog0 <<"\tGamestate: "<<tmh.getDif()<<std::endl;
 	serv = con;
-	serv->setGS(CGI->state);
 	CConnection &c(*con);
 	////////////////////////////////////////////////////
 	ui8 pom8;
@@ -411,6 +410,7 @@ void CClient::newGame( CConnection *con, StartInfo *si )
 		playerint[color]->init(cb);
 	}
 
+	serv->addStdVecItems(CGI->state);
 	hotSeat = (humanPlayers > 1);
 
 	playerint[255] =  CAIHandler::getNewAI(cb,conf.cc.defaultAI);

+ 2 - 2
client/GUIClasses.cpp

@@ -845,8 +845,8 @@ void SComponent::init(Etype Type, int Subtype, int Val)
 	switch (Type)
 	{
 	case artifact:
-		description = CGI->arth->artifacts[Subtype].Description();
-		subtitle = CGI->arth->artifacts[Subtype].Name();
+		description = CGI->arth->artifacts[Subtype]->Description();
+		subtitle = CGI->arth->artifacts[Subtype]->Name();
 		break;
 	case primskill:
 		oss << std::showpos << Val << " ";

+ 63 - 40
hch/CArtHandler.cpp

@@ -70,8 +70,9 @@ bool CArtifact::fitsAt (const std::map<ui16, ui32> &artifWorn, ui16 slotID) cons
 
 		VLC->arth->unequipArtifact(tempArtifWorn, slotID);
 
-		BOOST_FOREACH(ui32 constituentID, *constituents) {
-			const CArtifact& constituent = VLC->arth->artifacts[constituentID];
+		BOOST_FOREACH(ui32 constituentID, *constituents) 
+		{
+			const CArtifact& constituent = *VLC->arth->artifacts[constituentID];
 			const int slot = constituent.possibleSlots[0];
 
 			if (slot == 6 || slot == 7)
@@ -107,7 +108,7 @@ bool CArtifact::canBeAssembledTo (const std::map<ui16, ui32> &artifWorn, ui32 ar
 	if (constituentOf == NULL || !vstd::contains(*constituentOf, artifactID))
 		return false;
 
-	const CArtifact &artifact = VLC->arth->artifacts[artifactID];
+	const CArtifact &artifact = *VLC->arth->artifacts[artifactID];
 	assert(artifact.constituents);
 
 	BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
@@ -135,8 +136,9 @@ void CArtifact::addBonusesTo (BonusList *otherBonuses) const
 		otherBonuses->push_back(*i);
 
 	if (constituents != NULL) {
-		BOOST_FOREACH(ui32 artifactID, *constituents) {
-			VLC->arth->artifacts[artifactID].addBonusesTo(otherBonuses);
+		BOOST_FOREACH(ui32 artifactID, *constituents) 
+		{
+			VLC->arth->artifacts[artifactID]->addBonusesTo(otherBonuses);
 		}
 	}
 }
@@ -149,7 +151,7 @@ void CArtifact::removeBonusesFrom (BonusList *otherBonuses) const
 {
 	if (constituents != NULL) {
 		BOOST_FOREACH(ui32 artifactID, *constituents) {
-			VLC->arth->artifacts[artifactID].removeBonusesFrom(otherBonuses);
+			VLC->arth->artifacts[artifactID]->removeBonusesFrom(otherBonuses);
 		}
 	}
 
@@ -174,9 +176,9 @@ CArtHandler::CArtHandler()
 
 CArtHandler::~CArtHandler()
 {
-	for (std::vector<CArtifact>::iterator it = artifacts.begin(); it != artifacts.end(); ++it) {
-		delete it->constituents;
-		delete it->constituentOf;
+	for (std::vector<CArtifact*>::iterator it = artifacts.begin(); it != artifacts.end(); ++it) {
+		delete (*it)->constituents;
+		delete (*it)->constituentOf;
 	}
 }
 
@@ -196,7 +198,8 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
 	VLC->generaltexth->artifDescriptions.resize(ARTIFACTS_QUANTITY);
 	for (int i=0; i<ARTIFACTS_QUANTITY; i++)
 	{
-		CArtifact nart;
+		CArtifact *art = new CArtifact;
+		CArtifact &nart = *art;
 		nart.id=i;
 		loadToIt(VLC->generaltexth->artifNames[i],buf,it,4);
 		loadToIt(pom,buf,it,4);
@@ -290,7 +293,7 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
 				break;
 		}
 
-		artifacts.push_back(nart);
+		artifacts.push_back(&nart);
 	}
 	sortArts();
 	if(onlyTxt)
@@ -299,12 +302,15 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
 	addBonuses();
 
 	// Populate reverse mappings of combinational artifacts.
-	BOOST_FOREACH(CArtifact artifact, artifacts) {
-		if (artifact.constituents != NULL) {
-			BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
-				if (artifacts[constituentID].constituentOf == NULL)
-					artifacts[constituentID].constituentOf = new std::vector<ui32>();
-				artifacts[constituentID].constituentOf->push_back(artifact.id);
+	BOOST_FOREACH(CArtifact *artifact, artifacts) 
+	{
+		if (artifact->constituents != NULL) 
+		{
+			BOOST_FOREACH(ui32 constituentID, *artifact->constituents) 
+			{
+				if (artifacts[constituentID]->constituentOf == NULL)
+					artifacts[constituentID]->constituentOf = new std::vector<ui32>();
+				artifacts[constituentID]->constituentOf->push_back(artifact->id);
 			}
 		}
 	}
@@ -345,19 +351,19 @@ void CArtHandler::sortArts()
 {
 	for(int i=0;i<144;i++) //do 144, bo nie chcemy bzdurek
 	{
-		switch (artifacts[i].aClass)
+		switch (artifacts[i]->aClass)
 		{
 		case CArtifact::ART_TREASURE:
-			treasures.push_back(&(artifacts[i]));
+			treasures.push_back(artifacts[i]);
 			break;
 		case CArtifact::ART_MINOR:
-			minors.push_back(&(artifacts[i]));
+			minors.push_back(artifacts[i]);
 			break;
 		case CArtifact::ART_MAJOR:
-			majors.push_back(&(artifacts[i]));
+			majors.push_back(artifacts[i]);
 			break;
 		case CArtifact::ART_RELIC:
-			relics.push_back(&(artifacts[i]));
+			relics.push_back(artifacts[i]);
 			break;
 		}
 	}
@@ -368,8 +374,8 @@ void CArtHandler::giveArtBonus( int aid, Bonus::BonusType type, int val, int sub
 	Bonus added(Bonus::PERMANENT,type,Bonus::ARTIFACT,val,aid,subtype);
 	added.valType = valType;
 	if(type == Bonus::MORALE || Bonus::LUCK)
-		added.description = "\n" + artifacts[aid].Name()  + (val > 0 ? " +" : " ") + boost::lexical_cast<std::string>(val);
-	artifacts[aid].bonuses.push_back(added);
+		added.description = "\n" + artifacts[aid]->Name()  + (val > 0 ? " +" : " ") + boost::lexical_cast<std::string>(val);
+	artifacts[aid]->bonuses.push_back(added);
 }
 
 void CArtHandler::addBonuses()
@@ -614,7 +620,10 @@ void CArtHandler::addBonuses()
 
 void CArtHandler::clear()
 {
+	BOOST_FOREACH(CArtifact *art, artifacts)
+		delete art;
 	artifacts.clear();
+
 	treasures.clear();
 	minors.clear();
 	majors.clear();
@@ -632,23 +641,30 @@ void CArtHandler::equipArtifact
 {
 	unequipArtifact(artifWorn, slotID, bonuses);
 
-	const CArtifact &artifact = artifacts[artifactID];
+	const CArtifact &artifact = *artifacts[artifactID];
 
 	// Add artifact.
 	artifWorn[slotID] = artifactID;
 
 	// Add locks, in reverse order of being removed.
-	if (artifact.constituents != NULL) {
+	if (artifact.constituents != NULL) 
+	{
 		bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact.
 
-		BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
-			const CArtifact &constituent = artifacts[constituentID];
+		BOOST_FOREACH(ui32 constituentID, *artifact.constituents) 
+		{
+			const CArtifact &constituent = *artifacts[constituentID];
 
-			if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) {
+			if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) 
+			{
 				destConsumed = true;
-			} else {
-				BOOST_FOREACH(ui16 slot, constituent.possibleSlots) {
-					if (!vstd::contains(artifWorn, slot)) {
+			} 
+			else 
+			{
+				BOOST_FOREACH(ui16 slot, constituent.possibleSlots) 
+				{
+					if (!vstd::contains(artifWorn, slot)) 
+					{
 						artifWorn[slot] = 145;
 						break;
 					}
@@ -673,23 +689,30 @@ void CArtHandler::unequipArtifact
 	if (!vstd::contains(artifWorn, slotID))
 		return;
 
-	const CArtifact &artifact = artifacts[artifWorn[slotID]];
+	const CArtifact &artifact = *artifacts[artifWorn[slotID]];
 
 	// Remove artifact, if it's not already removed.
 	artifWorn.erase(slotID);
 
 	// Remove locks, in reverse order of being added.
-	if (artifact.constituents != NULL) {
+	if (artifact.constituents != NULL) 
+	{
 		bool destConsumed = false;
 
-		BOOST_FOREACH(ui32 constituentID, *artifact.constituents) {
-			const CArtifact &constituent = artifacts[constituentID];
+		BOOST_FOREACH(ui32 constituentID, *artifact.constituents) 
+		{
+			const CArtifact &constituent = *artifacts[constituentID];
 
-			if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) {
+			if (!destConsumed && vstd::contains(constituent.possibleSlots, slotID)) 
+			{
 				destConsumed = true;
-			} else {
-				BOOST_REVERSE_FOREACH(ui16 slot, constituent.possibleSlots) {
-					if (vstd::contains(artifWorn, slot) && artifWorn[slot] == 145) {
+			} 
+			else 
+			{
+				BOOST_REVERSE_FOREACH(ui16 slot, constituent.possibleSlots) 
+				{
+					if (vstd::contains(artifWorn, slot) && artifWorn[slot] == 145) 
+					{
 						artifWorn.erase(slot);
 						break;
 					}

+ 2 - 2
hch/CArtHandler.h

@@ -36,7 +36,7 @@ public:
 	std::vector<ui32> * constituents; // Artifacts IDs a combined artifact consists of, or NULL.
 	std::vector<ui32> * constituentOf; // Reverse map of constituents.
 	EartClass aClass;
-	ui32 id;
+	si32 id;
 	std::list<Bonus> bonuses; //bonuses given by artifact
 
 	template <typename Handler> void serialize(Handler &h, const int version)
@@ -50,7 +50,7 @@ class DLL_EXPORT CArtHandler //handles artifacts
 	void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype = -1, int valType = Bonus::BASE_NUMBER);
 public:
 	std::vector<CArtifact*> treasures, minors, majors, relics;
-	std::vector<CArtifact> artifacts;
+	std::vector<CArtifact *> artifacts;
 	std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
 
 	void loadArtifacts(bool onlyTxt);

+ 1 - 1
hch/CCreatureHandler.h

@@ -36,7 +36,7 @@ public:
 	std::string abilityText; //description of abilities
 	std::string abilityRefs; //references to abilities, in textformat
 	std::string animDefName;
-	ui32 idNumber;
+	si32 idNumber;
 	si8 faction; //-1 = neutral
 	ui8 doubleWide;
 

+ 1 - 1
hch/CHeroHandler.h

@@ -27,7 +27,7 @@ public:
 		BARBARIAN, BATTLEMAGE, BEASTMASTER, WITCH, PLANESWALKER, ELEMENTALIST};
 
 	std::string name; //name of hero
-	ui16 ID;
+	si32 ID;
 	ui32 lowStack[3], highStack[3]; //amount of units; described below
 	std::string refTypeStack[3]; //reference names of units appearing in hero's army if he is recruited in tavern
 	CHeroClass * heroClass;

+ 80 - 55
hch/CObjectHandler.cpp

@@ -46,11 +46,12 @@ extern boost::rand48 ran;
 std::map <ui8, std::set <ui8> > CGKeys::playerKeyMap;
 std::map <si32, std::vector<si32> > CGMagi::eyelist;
 BankConfig CGPyramid::pyramidConfig;
-std::map<ui16, Component*> CGArtMerchant::advMapArts;
-std::map<ui16, Component*> CGArtMerchant::townArts;
 ui8 CGObelisk::obeliskCount; //how many obelisks are on map
 std::map<ui8, ui8> CGObelisk::visited; //map: color_id => how many obelisks has been visited
 
+std::vector<const CArtifact *> CGTownInstance::merchantArtifacts;
+
+
 void IObjectInterface::onHeroVisit(const CGHeroInstance * h) const 
 {};
 
@@ -694,7 +695,7 @@ const CArtifact * CGHeroInstance::getArt(int pos) const
 {
 	int id = getArtAtPos(pos);
 	if(id>=0)
-		return &VLC->arth->artifacts[id];
+		return VLC->arth->artifacts[id];
 	else
 		return NULL;
 }
@@ -1098,16 +1099,21 @@ si32 CGHeroInstance::getArtPos(int aid) const
  */
 void CGHeroInstance::giveArtifact (ui32 aid)
 {
-	const CArtifact &artifact = VLC->arth->artifacts[aid];
+	const CArtifact &artifact = *VLC->arth->artifacts[aid];
 
-	if (artifact.isBig()) {
-		for (std::vector<ui16>::const_iterator it = artifact.possibleSlots.begin(); it != artifact.possibleSlots.end(); ++it) {
-			if (!vstd::contains(artifWorn, *it)) {
+	if (artifact.isBig()) 
+	{
+		for (std::vector<ui16>::const_iterator it = artifact.possibleSlots.begin(); it != artifact.possibleSlots.end(); ++it) 
+		{
+			if (!vstd::contains(artifWorn, *it)) 
+			{
 				VLC->arth->equipArtifact(artifWorn, *it, aid, &bonuses);
 				break;
 			}
 		}
-	} else {
+	} 
+	else 
+	{
 		artifacts.push_back(aid);
 	}
 }
@@ -1118,7 +1124,7 @@ void CGHeroInstance::recreateArtBonuses()
 	bonuses.remove_if(boost::bind(Bonus::IsFrom,_1,Bonus::ARTIFACT,0xffffff));
 	for (std::map<ui16,ui32>::iterator ari = artifWorn.begin(); ari != artifWorn.end(); ari++)
 	{
-		CArtifact &art = VLC->arth->artifacts[ari->second];
+		CArtifact &art = *VLC->arth->artifacts[ari->second];
 		art.addBonusesTo(&bonuses);
 	}
 }
@@ -1761,6 +1767,39 @@ void CGTownInstance::newTurn() const
 				cb->setObjProperty (id, 12, (*i)->id); //reset visitors for Mana Vortex
 		}
 	}
+
+	if(cb->getDate(2) == 1) //reset on new month
+	{
+		std::vector<CArtifact*>::iterator index;
+		for (ui8 i = 0; i < 3; ++i) //each tier
+		{	
+			int count = 0;
+			std::vector<CArtifact*> arts; //to avoid addition of different tiers
+			switch (i)
+			{
+			case 0:
+				cb->getAllowed (arts, CArtifact::ART_TREASURE);
+				count = 3; // first row - three treasures,
+				break;
+			case 1:
+				cb->getAllowed (arts, CArtifact::ART_MINOR);
+				count = 3; // second row three minors
+				break;
+			case 2:
+				cb->getAllowed (arts, CArtifact::ART_MAJOR);
+				count = 1; // and a third row - one major
+				break;
+			}
+			for (ui8 n = 0; n < count; n++)
+			{
+				
+// 				index = arts.begin() + val % arts.size();
+// 				advMapArts [advMapArts.size()] = new Component (Component::ARTIFACT, (*index)->id, 0, 0);
+// 				arts.erase(index);
+// 				val *= (id + n * i); //randomize
+			}
+		}
+	}
 }
 
 int3 CGTownInstance::getSightCenter() const
@@ -3027,7 +3066,7 @@ void CGArtifact::initObj()
 {
 	blockVisit = true;
 	if(ID == 5)
-		hoverName = VLC->arth->artifacts[subID].Name();
+		hoverName = VLC->arth->artifacts[subID]->Name();
 }
 
 void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
@@ -5791,41 +5830,6 @@ void CShop::setPropertyDer (ui8 what, ui32 val)
 			break;
 	}
 }
-void CGArtMerchant::reset(ui32 val)
-{//TODO: it should have 2 global pools instead of unique for each merchant:
-// 1) for town merchants - resets every month,
-// 2) for adv. map - resets only on game start
-	std::vector<CArtifact*>::iterator index;
-	for (ui8 i = 0; i < 3; ++i) //each tier
-	{	
-		int count = 0;
-		std::vector<CArtifact*> arts; //to avoid addition of different tiers
-		switch (i)
-		{
-			case 0:
-				cb->getAllowed (arts, CArtifact::ART_TREASURE);
-				count = 3; // first row - three treasures,
-				break;
-			case 1:
-				cb->getAllowed (arts, CArtifact::ART_MINOR);
-				count = 3; // second row three minors
-				break;
-			case 2:
-				cb->getAllowed (arts, CArtifact::ART_MAJOR);
-				count = 1; // and a third row - one major
-				break;
-		}
-		for (ui8 n = 0; n < count; n++)
-		{
-
-			index = arts.begin() + val % arts.size();
-			advMapArts [advMapArts.size()] = new Component (Component::ARTIFACT, (*index)->id, 0, 0);
-			arts.erase(index);
-			val *= (id + n * i); //randomize
-		}
-	}
-
-}
 
 void CGRefugeeCamp::reset(ui32 val)
 {
@@ -6186,16 +6190,6 @@ void CGMarket::onHeroVisit(const CGHeroInstance * h) const
 	cb->sendAndApply(&ow);
 }
 
-void CGMarket::initObj()
-{
-
-}
-
-void CGMarket::newTurn() const
-{
-
-}
-
 int CGMarket::getMarketEfficiency() const
 {
 	return 5;
@@ -6241,4 +6235,35 @@ std::vector<int> CGMarket::availableItemsIds(EMarketMode mode) const
 CGMarket::CGMarket()
 	:IMarket(this)
 {
+}
+
+std::vector<int> CGBlackMarket::availableItemsIds(EMarketMode mode) const
+{
+	switch(mode)
+	{
+	case ARTIFACT_RESOURCE:
+		return IMarket::availableItemsIds(mode);
+	case RESOURCE_ARTIFACT:
+		{
+			std::vector<int> ret;
+			BOOST_FOREACH(const CArtifact *a, artifacts)
+				if(a)
+					ret.push_back(a->id);
+				else
+					ret.push_back(-1);
+			return ret;
+		}
+	default:
+		return std::vector<int>();
+	}
+}
+
+void CGBlackMarket::initObj()
+{
+
+}
+
+void CGBlackMarket::newTurn() const
+{
+
 }

+ 16 - 18
hch/CObjectHandler.h

@@ -487,7 +487,7 @@ public:
 	std::pair<si32, si32> bonusValue;//var to store town bonuses (rampart = resources from mystic pond);
 
 	//////////////////////////////////////////////////////////////////////////
-
+	static std::vector<const CArtifact *> merchantArtifacts; //vector of artifacts available at Artifact merchant, NULLs possible (for making empty space when artifact is bought)
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
@@ -1095,21 +1095,6 @@ public:
 	}
 };
 
-class DLL_EXPORT CGArtMerchant : public CShop
-{
-///aka Black Market
-public:
-	static std::map<ui16, Component*> advMapArts;
-	static std::map<ui16, Component*> townArts;
-	void reset (ui32 val);
-	void onHeroVisit (const CGHeroInstance * h) const {};
-	
-	template <typename Handler> void serialize(Handler &h, const int version)
-	{
-		h & advMapArts & townArts & static_cast<CShop&>(*this);
-	}
-};
-
 class DLL_EXPORT CGRefugeeCamp : public CShop
 {
 public:
@@ -1164,8 +1149,6 @@ class DLL_EXPORT CGMarket : public CGObjectInstance, public IMarket
 public:
 	CGMarket();
 	void onHeroVisit(const CGHeroInstance * h) const; //open trading window
-	void initObj();
-	void newTurn() const; //reset artifacts for black market every month
 	
 	int getMarketEfficiency() const;
 	bool allowsTrade(EMarketMode mode) const;
@@ -1178,6 +1161,21 @@ public:
 	}
 };
 
+class DLL_EXPORT CGBlackMarket : public CGMarket
+{
+public:
+	std::vector<const CArtifact *> artifacts; //available artifacts
+
+	void initObj();
+	void newTurn() const; //reset artifacts for black market every month
+	std::vector<int> availableItemsIds(EMarketMode mode) const;
+	
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CGMarket&>(*this);
+	}
+};
+
 struct BankConfig
 {
 	BankConfig() {level = chance = upgradeChance = combatValue = value = rewardDifficulty = easiest = 0; };

+ 2 - 2
lib/CGameState.cpp

@@ -165,7 +165,7 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 
 	if(type == ART_NAMES)
 	{
-		dst = VLC->arth->artifacts[ser].Name();
+		dst = VLC->arth->artifacts[ser]->Name();
 	}
 	else if(type == CRE_PL_NAMES)
 	{
@@ -189,7 +189,7 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 	}
 	else if(type == ART_DESCR)
 	{
-		dst = VLC->arth->artifacts[ser].Description();
+		dst = VLC->arth->artifacts[ser]->Description();
 	}
 	else
 	{

+ 23 - 37
lib/Connection.cpp

@@ -16,6 +16,9 @@
 #include "../hch/CObjectHandler.h"
 #include "../hch/CCreatureHandler.h"
 #include "VCMI_Lib.h"
+#include "../hch/CArtHandler.h"
+#include "../hch/CHeroHandler.h"
+#include "../hch/CTownHandler.h"
 
 
 /*
@@ -66,7 +69,6 @@ void CConnection::init()
 	tlog0 << "Established connection with "<<pom<<std::endl;
 	wmx = new boost::mutex;
 	rmx = new boost::mutex;
-	gs = NULL;
 }
 
 CConnection::CConnection(std::string host, std::string port, std::string Name)
@@ -201,42 +203,6 @@ void CConnection::close()
 	}
 }
 
-
-CGObjectInstance *CConnection::loadObject()
-{
-	assert(gs);
-	si32 id;
-	*this >> id;
-	assert(id >= 0 && id < gs->map->objects.size());
-	return gs->map->objects[id];
-}
-
-void CConnection::saveObject( const CGObjectInstance *data )
-{
-	assert(gs);
-	assert(data);
-	*this << data->id;
-}
-
-CCreature * CConnection::loadCreature()
-{
-	si32 id;
-	*this >> id;
-	assert(id >= 0 && id < VLC->creh->creatures.size());
-	return VLC->creh->creatures[id];
-}
-
-void CConnection::saveCreature(const CCreature *data)
-{
-	assert(data);
-	*this << data->idNumber;
-}
-
-void CConnection::setGS( CGameState *state )
-{
-	gs = state;
-}
-
 bool CConnection::isOpen() const
 {
 	return socket && connected;
@@ -362,3 +328,23 @@ ui16 CTypeList::getTypeID( const std::type_info *type )
 	else
 		return 0;
 }
+
+CSerializer::~CSerializer()
+{
+
+}
+
+CSerializer::CSerializer()
+{
+	smartVectorMembersSerialization = false;
+}
+
+
+void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
+{
+	registerVectoredType(&gs->map->objects, &CGObjectInstance::id);
+	registerVectoredType(&lib->creh->creatures, &CCreature::idNumber);
+	registerVectoredType(&lib->arth->artifacts, &CArtifact::id);
+	registerVectoredType(&lib->heroh->heroes, &CHero::ID);
+	smartVectorMembersSerialization = true;
+}

+ 117 - 97
lib/Connection.h

@@ -20,12 +20,16 @@
 #include <boost/mpl/equal_to.hpp>
 #include <boost/mpl/int.hpp>
 #include <boost/mpl/identity.hpp>
+#include <boost/any.hpp>
 
 const ui32 version = 723;
 class CConnection;
 class CGObjectInstance;
 class CGameState;
 class CCreature;
+class LibClasses;
+class CHero;
+extern DLL_EXPORT LibClasses * VLC;
 namespace mpl = boost::mpl;
 
 /*
@@ -223,7 +227,81 @@ struct SerializationLevel
 	static const int value = SerializationLevel::type::value;
 };
 
-class DLL_EXPORT CSaverBase
+template <typename T>
+struct VectorisedObjectInfo
+{
+	const std::vector<T*> *vector;	//pointer to the appropriate vector
+	const si32 T::*idPtr;			//pointer to the field representing the position in the vector
+
+	VectorisedObjectInfo(const std::vector<T*> *Vector, const si32 T::*IdPtr)
+		:vector(Vector), idPtr(IdPtr)
+	{
+	}
+};
+
+class DLL_EXPORT CSerializer
+{
+public:
+	typedef std::map<const std::type_info *, boost::any, TypeComparer> TTypeVecMap;
+	TTypeVecMap vectors; //entry must be a pointer to vector containing pointers to the objects of key type
+
+	bool smartVectorMembersSerialization;
+
+	CSerializer();
+	~CSerializer();
+
+	template <typename T>
+	void registerVectoredType(const std::vector<T*> *Vector, const si32 T::*IdPtr)
+	{
+		vectors[&typeid(T)] = VectorisedObjectInfo<T>(Vector, IdPtr);
+	}
+
+	template <typename T>
+	const VectorisedObjectInfo<T> *getVectorisedTypeInfo()
+	{
+		const std::type_info *myType = NULL;
+// 
+// 		if(boost::is_base_of<CGObjectInstance, T>::value) //ugly workaround to support also types derived from CGObjectInstance -> if we encounter one, treat it aas CGObj..
+// 			myType = &typeid(CGObjectInstance);
+// 		else
+			 myType = &typeid(T);
+
+		TTypeVecMap::iterator i = vectors.find(myType);
+		if(i == vectors.end())
+			return NULL;
+		else
+		{
+			assert(!i->second.empty());
+			assert(i->second.type() == typeid(VectorisedObjectInfo<T>));
+			VectorisedObjectInfo<T> *ret = &(boost::any_cast<VectorisedObjectInfo<T>&>(i->second));
+			return ret;
+		}
+	}
+
+	template <typename T>
+	T* getVectorItemFromId(const VectorisedObjectInfo<T> &oInfo, si32 id) const
+	{
+		if(id < 0)
+			return NULL;
+
+		assert(oInfo.vector);
+		assert(oInfo.vector->size() > id);
+		return (*oInfo.vector)[id];
+	}
+
+	template <typename T>
+	si32 getIdFromVectorItem(const VectorisedObjectInfo<T> &oInfo, const T* obj) const
+	{
+		if(!obj)
+			return -1;
+
+		return obj->*oInfo.idPtr;
+	}
+
+	void addStdVecItems(CGameState *gs, LibClasses *lib = VLC);
+};
+
+class DLL_EXPORT CSaverBase : public virtual CSerializer
 {
 };
 
@@ -247,6 +325,18 @@ public:
 	}
 };
 
+template <typename T> //metafunction returning CGObjectInstance if T is its derivate or T elsewise
+struct VectorisedTypeFor
+{
+	typedef typename 
+		//if
+		mpl::eval_if<boost::is_base_of<CGObjectInstance,T>,
+		mpl::identity<CGObjectInstance>,
+		//else
+		mpl::identity<T>
+		>::type type;
+};
+
 template <typename Serializer> class DLL_EXPORT COSer : public CSaverBase
 {
 public:
@@ -313,6 +403,17 @@ public:
 		if(!hlp)
 			return;
 
+ 		if(smartVectorMembersSerialization)
+		{
+			typedef typename boost::remove_const<typename boost::remove_pointer<T>::type>::type TObjectType;
+			typedef typename VectorisedTypeFor<TObjectType>::type VType;
+ 			if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
+ 			{
+ 				*this << getIdFromVectorItem<VType>(*info, data);
+ 				return;
+ 			}
+ 		}
+
 		if(smartPointerSerialization)
 		{
 			std::map<const void*,ui32>::iterator i = savedPointers.find(data);
@@ -429,7 +530,7 @@ public:
 
 
 
-class DLL_EXPORT CLoaderBase
+class DLL_EXPORT CLoaderBase : public virtual CSerializer
 {};
 
 class CBasicPointerLoader
@@ -456,7 +557,6 @@ public:
 	}
 };
 
-
 template <typename Serializer> class DLL_EXPORT CISer : public CLoaderBase
 {
 public:
@@ -562,6 +662,19 @@ public:
 			data = NULL;
 			return;
 		}
+				
+		if(smartVectorMembersSerialization)
+		{
+			typedef typename boost::remove_const<typename boost::remove_pointer<T>::type>::type TObjectType; //eg: const CGHeroInstance * => CGHeroInstance
+			typedef typename VectorisedTypeFor<TObjectType>::type VType;									 //eg: CGHeroInstance -> CGobjectInstance
+			if(const VectorisedObjectInfo<VType> *info = getVectorisedTypeInfo<VType>())
+			{
+				si32 id;
+				*this >> id;
+				data = static_cast<T>(getVectorItemFromId(*info, id));
+				return;
+			}
+		}
 
 		ui32 pid = -1; //pointer id (or maybe rather pointee id) 
 		if(smartPointerSerialization)
@@ -711,7 +824,7 @@ typedef boost::asio::basic_socket_acceptor<boost::asio::ip::tcp, boost::asio::so
 class DLL_EXPORT CConnection
 	:public CISer<CConnection>, public COSer<CConnection>
 {
-	CGameState *gs;
+	//CGameState *gs;
 	CConnection(void);
 
 	void init();
@@ -735,99 +848,6 @@ public:
     template<class T>
     CConnection &operator&(const T&);
 	~CConnection(void);
-	void setGS(CGameState *state);
-
-	CGObjectInstance *loadObject(); //reads id from net and returns that obj
-	void saveObject(const CGObjectInstance *data);
-	CCreature *loadCreature(); //reads id from net and returns that obj
-	void saveCreature(const CCreature *data);
-
-
-	template<typename T>
-	struct loadObjectHelper
-	{
-		static void invoke(CConnection &s, T &data, ui16 tid)
-		{
-			data = static_cast<T>(s.loadObject());
-		}
-	};
-	template<typename T>
-	struct loadCreatureHelper
-	{
-		static void invoke(CConnection &s, T &data, ui16 tid)
-		{
-			data = static_cast<T>(s.loadCreature());
-		}
-	};
-	template<typename T>
-	struct loadRestHelper
-	{
-		static void invoke(CConnection &s, T &data, ui16 tid)
-		{
-			s.CISer<CConnection>::loadPointerHlp(tid, data, -1);
-		}
-	};
-	template<typename T>
-	struct saveObjectHelper
-	{
-		static void invoke(CConnection &s, const T &data, ui16 tid)
-		{
-			//CGObjectInstance *&hlp = const_cast<CGObjectInstance*&>(data); //for loading pointer to const obj we must remove the qualifier
-			s.saveObject(data);
-		}
-	};
-	template<typename T>
-	struct saveCreatureHelper
-	{
-		static void invoke(CConnection &s, const T &data, ui16 tid)
-		{
-			//CGObjectInstance *&hlp = const_cast<CGObjectInstance*&>(data); //for loading pointer to const obj we must remove the qualifier
-			s.saveCreature(data);
-		}
-	};
-	template<typename T>
-	struct saveRestHelper
-	{
-		static void invoke(CConnection &s, const T &data, ui16 tid)
-		{
-			s.COSer<CConnection>::savePointerHlp(tid, data);
-		}
-	};
-
-
-	//"overload" loading pointer procedure
-	template <typename T>
-	void loadPointerHlp( ui16 tid, T & data, ui32 pid )
-	{
-		typedef typename 
-			//if
-			mpl::eval_if< boost::is_base_of<CGObjectInstance, typename boost::remove_pointer<T>::type>,
-			mpl::identity<loadObjectHelper<T> >,
-			//else if
-			mpl::eval_if< boost::is_base_of<CCreature, typename boost::remove_pointer<T>::type>,
-			mpl::identity<loadCreatureHelper<T> >,
-			//else
-			mpl::identity<loadRestHelper<T> >
-			> >::type typex;
-		typex::invoke(*this, data, tid);
-	}
-
-	//"overload" saving pointer procedure
-	template <typename T>
-	void savePointerHlp( ui16 tid, const T & data )
-	{
-		typedef typename 
-			//if
-			mpl::eval_if< boost::is_base_of<CGObjectInstance, typename boost::remove_pointer<T>::type>,
-				mpl::identity<saveObjectHelper<T> >,
-			//else if
-			mpl::eval_if< boost::is_base_of<CCreature, typename boost::remove_pointer<T>::type>,
-			mpl::identity<saveCreatureHelper<T> >,
-			//else
-				mpl::identity<saveRestHelper<T> >
-			> >::type typex;
-		typex::invoke(*this, data, tid);
-	}
 };
 
 #endif // __CONNECTION_H__

+ 3 - 3
lib/IGameCallback.cpp

@@ -181,8 +181,8 @@ void IGameCallback::getAllowedArts(std::vector<CArtifact*> &out, std::vector<CAr
 	{
 		for (int i = 0; i < VLC->arth->artifacts.size(); i++)
 		{
-			if (VLC->arth->artifacts[i].aClass == flag)
-				(VLC->arth->*arts).push_back(&(VLC->arth->artifacts[i]));
+			if (VLC->arth->artifacts[i]->aClass == flag)
+				(VLC->arth->*arts).push_back(VLC->arth->artifacts[i]);
 		}
 	}
 
@@ -209,7 +209,7 @@ void IGameCallback::getAllowed(std::vector<CArtifact*> &out, int flags)
 	if (!out.size()) //no arts are avaliable
 	{
 		out.resize(64);
-		std::fill_n(out.begin(), 64, &(VLC->arth->artifacts[2])); //magic
+		std::fill_n(out.begin(), 64, VLC->arth->artifacts[2]); //magic
 	}
 }
 

+ 17 - 0
lib/NetPacks.h

@@ -22,6 +22,8 @@ class CGameState;
 class CGameHandler;
 class CConnection;
 
+class CArtifact;
+
 struct CPack
 {
 	ui16 type;
@@ -642,6 +644,21 @@ struct NewObject  : public CPackForClient //518
 	}
 };
 
+struct SetAvailableArtifacts  : public CPackForClient //519
+{
+	SetAvailableArtifacts(){type = 519;};
+	//void applyCl(CClient *cl);
+	DLL_EXPORT void applyGs(CGameState *gs);
+
+	si32 id; //two variants: id < 0: set artifact pool for Artifact Merchants in towns; id >= 0: set pool for adv. map Black Market (id is the id of Black Market instance then)
+	std::vector<const CArtifact *> arts;
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & id & arts;
+	}
+};
+
 struct NewTurn : public CPackForClient //101
 {
 	DLL_EXPORT void applyGs(CGameState *gs);

+ 21 - 2
lib/NetPacksLib.cpp

@@ -487,7 +487,7 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
 		if(h->getArtPos(id) >= 0)
 			continue;
 
-		CArtifact &art = VLC->arth->artifacts[id];
+		CArtifact &art = *VLC->arth->artifacts[id];
 		art.addBonusesTo(&h->bonuses);
 		art.addBonusesTo(&gained);
 	}
@@ -503,7 +503,7 @@ DLL_EXPORT void SetHeroArtifacts::applyGs( CGameState *gs )
 		if(h->getArtPos(id) >= 0)
 			continue;
 
-		CArtifact &art = VLC->arth->artifacts[id];
+		CArtifact &art = *VLC->arth->artifacts[id];
 		art.removeBonusesFrom(&h->bonuses);
 		art.addBonusesTo(&lost);
 	}
@@ -606,6 +606,25 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
 	assert(o->defInfo);
 }
 
+DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
+{
+	if(id >= 0)
+	{
+		if(CGBlackMarket *bm = dynamic_cast<CGBlackMarket*>(gs->map->objects[id]))
+		{
+			bm->artifacts = arts;
+		}
+		else
+		{
+			tlog1 << "Wrong black market id!" << std::endl;
+		}
+	}
+	else
+	{
+		CGTownInstance::merchantArtifacts = arts;
+	}
+}
+
 DLL_EXPORT void NewTurn::applyGs( CGameState *gs )
 {
 	gs->day = day;

+ 1 - 0
lib/map.h

@@ -373,6 +373,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
 		h & CGMagi::eyelist;
 		h & CGPyramid::pyramidConfig;
 		h & CGObelisk::obeliskCount & CGObelisk::visited;
+		h & CGTownInstance::merchantArtifacts;
 
 		for(unsigned int i=0; i<objects.size(); i++)
 		{

+ 4 - 4
server/CGameHandler.cpp

@@ -1944,7 +1944,7 @@ void CGameHandler::stopHeroVisitCastle(int obj, int heroID)
 void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1 - first free slot in backpack
 {
 	const CGHeroInstance* h = getHero(hid);
-	const CArtifact &art = VLC->arth->artifacts[artid];
+	const CArtifact &art = *VLC->arth->artifacts[artid];
 
 	SetHeroArtifacts sha;
 	sha.hid = hid;
@@ -2922,7 +2922,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
 			return false;
 		}
 
-		const CArtifact &artifact = VLC->arth->artifacts[assembleTo];
+		const CArtifact &artifact = *VLC->arth->artifacts[assembleTo];
 
 		if (artifact.constituents == NULL) {
 			complain("Not a combinational artifact.");
@@ -2975,7 +2975,7 @@ bool CGameHandler::assembleArtifacts (si32 heroID, ui16 artifactSlot, bool assem
 		// Perform disassembly.
 		bool destConsumed = false; // Determines which constituent that will be counted for together with the artifact.
 		BOOST_FOREACH(ui32 constituentID, *destArtifact->constituents) {
-			const CArtifact &constituent = VLC->arth->artifacts[constituentID];
+			const CArtifact &constituent = *VLC->arth->artifacts[constituentID];
 
 			if (!destConsumed && vstd::contains(constituent.possibleSlots, artifactSlot)) {
 				sha.artifWorn[artifactSlot] = constituentID;
@@ -3015,7 +3015,7 @@ bool CGameHandler::buyArtifact( ui32 hid, si32 aid )
 	}
 	else if(aid < 7  &&  aid > 3) //war machine
 	{
-		int price = VLC->arth->artifacts[aid].price;
+		int price = VLC->arth->artifacts[aid]->price;
 		if(vstd::contains(hero->artifWorn,ui16(9+aid)) && complain("Hero already has this machine!")
 			|| !vstd::contains(town->builtBuildings,si32(16)) && complain("No blackismith!")
 			|| gs->getPlayer(hero->getOwner())->resources[6] < price  && complain("Not enough gold!")  //no gold

+ 4 - 4
server/CVCMIServer.cpp

@@ -94,7 +94,7 @@ void CVCMIServer::newGame(CConnection *c)
 
 	StartInfo startInfoCpy = *si;
 	gh.init(si,rand());
-	c->setGS(gh.gs);
+	c->addStdVecItems(gh.gs);
 
 	CConnection* cc; //tcp::socket * ss;
 	for(int i=0; i<clients; i++)
@@ -114,7 +114,7 @@ void CVCMIServer::newGame(CConnection *c)
 				continue;
 			}
 			cc = new CConnection(s,NAME);
-			cc->setGS(gh.gs);
+			cc->addStdVecItems(gh.gs);
 		}	
 		gh.conns.insert(cc);
 	}
@@ -201,7 +201,7 @@ void CVCMIServer::loadGame( CConnection *c )
 		tlog0 <<"Reading handlers"<<std::endl;
 
 		lf >> (gh.gs);
-		c->setGS(gh.gs);
+		c->addStdVecItems(gh.gs);
 		tlog0 <<"Reading gamestate"<<std::endl;
 	}
 
@@ -230,7 +230,7 @@ void CVCMIServer::loadGame( CConnection *c )
 				continue;
 			}
 			cc = new CConnection(s,NAME);
-			cc->setGS(gh.gs);
+			cc->addStdVecItems(gh.gs);
 		}	
 		gh.conns.insert(cc);
 	}