Browse Source

some changes

mateuszb 15 years ago
parent
commit
23c501b79e

+ 3 - 3
CCallback.cpp

@@ -232,7 +232,7 @@ const CGHeroInstance * CCallback::getHeroInfo(int val, int mode) const //mode =
 	}
 	else //object id
 	{
-		return static_cast<const CGHeroInstance*>(gs->map->objects[val]);
+		return static_cast<const CGHeroInstance*>(+gs->map->objects[val]);
 	}
 	return NULL;
 }
@@ -599,7 +599,7 @@ const CGTownInstance *CCallback::battleGetDefendedTown()
 	if(!gs->curB || gs->curB->tid == -1)
 		return NULL;
 
-	return static_cast<const CGTownInstance *>(gs->map->objects[gs->curB->tid]);
+	return static_cast<const CGTownInstance *>(+gs->map->objects[gs->curB->tid]);
 }
 
 ui8 CCallback::battleGetWallState(int partOfWall)
@@ -705,7 +705,7 @@ std::vector < const CGObjectInstance * > CCallback::getFlaggableObjects(int3 pos
 
 	std::vector < const CGObjectInstance * > ret;
 
-	std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[pos.x][pos.y][pos.z].objects;
+	const std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & objs = CGI->mh->ttiles[pos.x][pos.y][pos.z].objects;
 	for(size_t b=0; b<objs.size(); ++b)
 	{
 		if(objs[b].first->tempOwner!=254 && !((objs[b].first->defInfo->blockMap[pos.y - objs[b].first->pos.y + 5] >> (objs[b].first->pos.x - pos.x)) & 1))

+ 4 - 4
client/CCastleInterface.cpp

@@ -56,7 +56,7 @@ int hordeToDwellingID(int bid)//helper, converts horde buiding ID into correspon
 	}
 }
 
-CBuildingRect::CBuildingRect(Structure *Str)
+CBuildingRect::CBuildingRect(const Structure *Str)
 	:CShowableAnim(0, 0, Str->defName, CShowableAnim::FLAG_BASE),
 	moi(false), str(Str)
 {
@@ -901,7 +901,7 @@ void CCastleInterface::recreateBuildings()
 		{
 			if(CGI->townh->structures[town->subID].find(*i)!=CGI->townh->structures[town->subID].end()) //we have info about that structure
 			{
-				Structure * st = CGI->townh->structures[town->subID][*i];
+				const Structure * st = CGI->townh->structures[town->subID][*i];
 				if(st->group<0) //no group - just add it
 				{
 					buildings.push_back(new CBuildingRect(st));
@@ -1777,7 +1777,7 @@ void CFortScreen::draw( CCastleInterface * owner, bool first)
 	for(int i=0;i<fortSize; i++)
 	{
 		int dwelling;// ID of buiding with this creature
-		CCreature *c;
+		const CCreature *c;
 		bool present = true;
 		if ( i < CREATURES_PER_TOWN )
 		{
@@ -1925,7 +1925,7 @@ void CMageGuildScreen::close()
 	GH.popIntTotally(this);
 }
 
-CMageGuildScreen::Scroll::Scroll(CSpell *Spell)
+CMageGuildScreen::Scroll::Scroll(const CSpell *Spell)
 	:spell(Spell)
 {
 	used = LCLICK | RCLICK | HOVER;

+ 4 - 4
client/CCastleInterface.h

@@ -38,10 +38,10 @@ class CBuildingRect : public CShowableAnim
 {
 public:
 	bool moi; //motion interested is active
-	Structure* str;
+	const Structure* str;
 	SDL_Surface* border;
 	SDL_Surface* area;
-	CBuildingRect(Structure *Str); //c-tor
+	CBuildingRect(const Structure *Str); //c-tor
 	~CBuildingRect(); //d-tor
 	void activate();
 	void deactivate();
@@ -238,9 +238,9 @@ public:
 	class Scroll : public CIntObject
 	{
 	public:
-		CSpell *spell;
+		const CSpell *spell;
 
-		Scroll(CSpell *Spell);
+		Scroll(const  CSpell *Spell);
 		void clickLeft(tribool down, bool previousState);
 		void clickRight(tribool down, bool previousState);
 		void hover(bool on);

+ 22 - 12
client/CGameInfo.h

@@ -1,6 +1,7 @@
 #ifndef __CGAMEINFO_H__
 #define __CGAMEINFO_H__
 #include "../global.h"
+#include "../lib/ConstTransitivePtr.h"
 
 
 /*
@@ -38,20 +39,21 @@ struct Mapa;
 */
 class CGameInfo
 {
-	/*const*/ CGameState * state; //don't touch it in client's code
+	CGameState * state; //don't touch it in client's code
 public:
-	/*const*/ CArtHandler * arth;
-	/*const*/ CHeroHandler * heroh;
-	/*const*/ CCreatureHandler * creh;
-	/*const*/ CSpellHandler * spellh;
-	/*const*/ CMapHandler * mh;
-	/*const*/ CBuildingHandler * buildh;
-	/*const*/ CObjectHandler * objh;
+	CArtHandler * arth;
+	CHeroHandler * heroh;
+	CCreatureHandler * creh;
+	CSpellHandler * spellh;
+	CObjectHandler * objh;
+	CDefObjInfoHandler * dobjinfo;
+	CGeneralTextHandler * generaltexth;
+	CMapHandler * mh;
+	CBuildingHandler * buildh;
 	CSoundHandler * soundh;
 	CMusicHandler * musich;
-	/*const*/ CDefObjInfoHandler * dobjinfo;
-	/*const*/ CTownHandler * townh;
-	/*const*/ CGeneralTextHandler * generaltexth;
+	CTownHandler * townh;
+	//CTownHandler * townh;
 	CConsoleHandler * consoleh;
 	CCursorHandler * curh;
 	CVideoPlayer * videoh;
@@ -64,7 +66,15 @@ public:
 	CGameInfo();
 };
 
-
+//	ConstTransitivePtr<CGameState> state; //don't touch it in client's code
+// public:
+// 	ConstTransitivePtr<CArtHandler> arth;
+// 	ConstTransitivePtr<CHeroHandler> heroh;
+// 	ConstTransitivePtr<CCreatureHandler> creh;
+// 	ConstTransitivePtr<CSpellHandler> spellh;
+// 	ConstTransitivePtr<CObjectHandler> objh;
+// 	ConstTransitivePtr<CDefObjInfoHandler> dobjinfo;
+// 	ConstTransitivePtr<CGeneralTextHandler> generaltexth;
 
 
 

+ 7 - 8
client/CHeroWindow.cpp

@@ -70,7 +70,6 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	garr = NULL;
-	curBack = NULL;
 	curHero = NULL;
 	player = hero->tempOwner;
 
@@ -181,7 +180,7 @@ void CHeroWindow::setHero(const CGHeroInstance *hero)
 	{
 		delete garr;
 		OBJ_CONSTRUCTION_CAPTURING_ALL;
-		garr = new CGarrisonInt(80, 493, 8, Point(), curBack->bg, Point(16,486), curHero);
+		garr = new CGarrisonInt(80, 493, 8, Point(), background->bg, Point(16,486), curHero);
 	}
 
 	AdventureMapButton * split = NULL;
@@ -320,10 +319,10 @@ void CHeroWindow::showAll(SDL_Surface * to)
 	}
 	 
 	//morale and luck printing
-	blitAt(graphics->luck42->ourImages[curHero->LuckVal()+3].bitmap, 239, 182, to);
-	blitAt(graphics->morale42->ourImages[curHero->MoraleVal()+3].bitmap, 181, 182, to);
+	blitAtLoc(graphics->luck42->ourImages[curHero->LuckVal()+3].bitmap, 239, 182, to);
+	blitAtLoc(graphics->morale42->ourImages[curHero->MoraleVal()+3].bitmap, 181, 182, to);
 	 
-	blitAt(flags->ourImages[player].bitmap, 606, 8, to);
+	blitAtLoc(flags->ourImages[player].bitmap, 606, 8, to);
 	 
 	//hero list blitting
 	 
@@ -334,7 +333,7 @@ void CHeroWindow::showAll(SDL_Surface * to)
 	 		// Only display heroes that are not in garrison
 	 		continue;
 	 
-	 	blitAt(graphics->portraitSmall[cur->portrait], 611, 87+pos*54, to);
+	 	blitAtLoc(graphics->portraitSmall[cur->portrait], 611, 87+pos*54, to);
 	 	//printing yellow border
 	 	if(cur->name == curHero->name)
 	 	{
@@ -354,13 +353,13 @@ void CHeroWindow::showAll(SDL_Surface * to)
 	//secondary skills
 	for(size_t v=0; v<std::min(secSkillAreas.size(), curHero->secSkills.size()); ++v)
 	{
-	 	blitAt(graphics->abils44->ourImages[curHero->secSkills[v].first*3+3+curHero->secSkills[v].second-1].bitmap, v%2 ? 161 : 18, 276 + 48 * (v/2), to);
+	 	blitAtLoc(graphics->abils44->ourImages[curHero->secSkills[v].first*3+3+curHero->secSkills[v].second-1].bitmap, v%2 ? 161 : 18, 276 + 48 * (v/2), to);
 	 	printAtLoc(CGI->generaltexth->levels[curHero->secSkills[v].second-1], v%2 ? 212 : 68, 280 + 48 * (v/2), FONT_SMALL, zwykly, to);
 	 	printAtLoc(CGI->generaltexth->skillName[curHero->secSkills[v].first], v%2 ? 212 : 68, 300 + 48 * (v/2), FONT_SMALL, zwykly, to);
 	}
 	 
 	//printing special ability
-	blitAt(graphics->un44->ourImages[curHero->subID].bitmap, 18, 180, to);
+	blitAtLoc(graphics->un44->ourImages[curHero->subID].bitmap, 18, 180, to);
 	printAtLoc(CGI->generaltexth->jktexts[5].substr(1, CGI->generaltexth->jktexts[5].size()-2), 69, 183, FONT_SMALL, tytulowy, to);
 	printAtLoc(CGI->generaltexth->hTxts[curHero->subID].bonusName, 69, 205, FONT_SMALL, zwykly, to);
 	 

+ 1 - 1
client/CHeroWindow.h

@@ -42,7 +42,7 @@ class CHeroWindow: public CWindowWithGarrison
 {
 	enum ELabel {};
 	std::map<ELabel, CLabel*> labels;
-	CPicture *background, *curBack;
+	CPicture *background;
 	CGStatusBar * ourBar; //heroWindow's statusBar
 
 	//general graphics

+ 1 - 1
client/CKingdomInterface.cpp

@@ -254,7 +254,7 @@ void CKingdomInterface::showAll( SDL_Surface * to/*=NULL*/)
 		ObjList[i]->hoverText = "";
 
 	int skipCount=0, curPos=objPos<0?(-objPos):0;
-	for (std::map<int,std::pair<int, std::string*> >::iterator it=objList.begin(); it!= objList.end(); it++)
+	for (std::map<int,std::pair<int, const std::string*> >::iterator it=objList.begin(); it!= objList.end(); it++)
 	{
 		if (skipCount<objPos)//we will show only objects from objPos
 		{

+ 1 - 1
client/CKingdomInterface.h

@@ -118,7 +118,7 @@ public:
 	//objects list
 	int objSize, objPos;
 	CDefEssential *objPics;
-	std::map<int,std::pair<int, std::string*> > objList; //dwelling ID, count, hover text
+	std::map<int,std::pair<int, const std::string*> > objList; //dwelling ID, count, hover text
 	std::vector <HoverableArea* > ObjList;//list of dwellings
 	AdventureMapButton* ObjUp, *ObjDown, *ObjTop, *ObjBottom;//buttons for dwellings list
 

+ 5 - 2
client/mapHandler.cpp

@@ -419,7 +419,10 @@ void CMapHandler::init()
 // top_tile top left tile to draw. Not necessarily visible.
 // extRect, extRect = map window on screen
 // moveX, moveY: when a hero is in movement indicates how to shift the map. Range is -31 to + 31.
-void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, const std::vector< std::vector< std::vector<unsigned char> > > * visibilityMap, bool otherHeroAnim, unsigned char heroAnim, SDL_Surface * extSurf, const SDL_Rect * extRect, int moveX, int moveY, bool puzzleMode)
+void CMapHandler::terrainRect(int3 top_tile, unsigned char anim,
+	const std::vector< std::vector< std::vector<unsigned char> > > * visibilityMap,
+	bool otherHeroAnim, unsigned char heroAnim, SDL_Surface * extSurf, const SDL_Rect * extRect,
+	int moveX, int moveY, bool puzzleMode) const
 {
 	// Width and height of the portion of the map to process. Units in tiles.
 	unsigned int dx = tilesW;
@@ -778,7 +781,7 @@ void CMapHandler::terrainRect(int3 top_tile, unsigned char anim, const std::vect
 	SDL_SetClipRect(extSurf, &prevClip); //restoring clip_rect
 }
 
-std::pair<SDL_Surface *, bool> CMapHandler::getVisBitmap( const int3 & pos, const std::vector< std::vector< std::vector<unsigned char> > > & visibilityMap )
+std::pair<SDL_Surface *, bool> CMapHandler::getVisBitmap( const int3 & pos, const std::vector< std::vector< std::vector<unsigned char> > > & visibilityMap ) const
 {
 	static const int visBitmaps[256] = {-1, 34, -1, 4, 22, 22, 4, 4, 36, 36, 38, 38, 47, 47, 38, 38, 3, 25, 12, 12, 3, 25, 12, 12,
 		9, 9, 6, 6, 9, 9, 6, 6, 35, 34, 4, 4, 22, 22, 4, 4, 36, 36, 38, 38, 47, 47, 38, 38, 26, 49, 28, 28, 26, 49, 28,

+ 2 - 2
client/mapHandler.h

@@ -102,7 +102,7 @@ public:
 	CMapHandler(); //c-tor
 	~CMapHandler(); //d-tor
 
-	std::pair<SDL_Surface *, bool> getVisBitmap(const int3 & pos, const std::vector< std::vector< std::vector<unsigned char> > > & visibilityMap); //returns appropriate bitmap and info if alpha blitting is necessary
+	std::pair<SDL_Surface *, bool> getVisBitmap(const int3 & pos, const std::vector< std::vector< std::vector<unsigned char> > > & visibilityMap) const; //returns appropriate bitmap and info if alpha blitting is necessary
 
 	std::vector< std::string > getObjDescriptions(int3 pos); //returns desriptions of objects blocking given position
 	void getTerrainDescr(const int3 &pos, std::string & out, bool terName); //if tername == false => empty string when tile is clear
@@ -118,7 +118,7 @@ public:
 	void roadsRiverTerrainInit();
 	void prepareFOWDefs();
 
-	void terrainRect(int3 top_tile, unsigned char anim, const std::vector< std::vector< std::vector<unsigned char> > > * visibilityMap, bool otherHeroAnim, unsigned char heroAnim, SDL_Surface * extSurf, const SDL_Rect * extRect, int moveX, int moveY, bool puzzleMode);
+	void terrainRect(int3 top_tile, unsigned char anim, const std::vector< std::vector< std::vector<unsigned char> > > * visibilityMap, bool otherHeroAnim, unsigned char heroAnim, SDL_Surface * extSurf, const SDL_Rect * extRect, int moveX, int moveY, bool puzzleMode) const;
 	void updateWater();
 	unsigned char getHeroFrameNum(unsigned char dir, bool isMoving) const; //terrainRect helper function
 	void validateRectTerr(SDL_Rect * val, const SDL_Rect * ext); //terrainRect helper

+ 28 - 0
global.h

@@ -91,6 +91,7 @@ const int HEROI_TYPE = 34,
 	CREI_TYPE = 54,
 	EVENTI_TYPE = 26;
 
+const int CRE_LEVELS = 10;
 const int F_NUMBER = 9; //factions (town types) quantity
 const int PLAYER_LIMIT = 8; //player limit per map
 const int ALL_PLAYERS = 255; //bitfield
@@ -166,6 +167,28 @@ enum EAlignment
 template<typename T, size_t N> char (&_ArrayCountObj(const T (&)[N]))[N];  
 #define ARRAY_COUNT(arr)    (sizeof(_ArrayCountObj(arr)))
 
+
+
+//a normal std::map with consted operator[] for sanity
+template<typename KeyT, typename ValT>
+class bmap : public std::map<KeyT, ValT>
+{
+public:
+	const ValT & operator[](KeyT key) const
+	{
+		const_iterator it = find(*this, key);
+		return it->second;
+	}
+	ValT & operator[](KeyT key) 
+	{
+		return static_cast<std::map<KeyT, ValT> &>(*this)[key];
+	}	
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<std::map<KeyT, ValT> &>(*this);
+	}
+};
+
 namespace vstd
 {
 	template <typename Container, typename Item>
@@ -178,6 +201,11 @@ namespace vstd
 	{
 		return c.find(i)!=c.end();
 	}
+	template <typename V, typename Item, typename Item2>
+	bool contains(const bmap<Item,V> & c, const Item2 &i) //returns true if map c contains item i
+	{
+		return c.find(i)!=c.end();
+	}
 	template <typename Container1, typename Container2>
 	typename Container2::iterator findFirstNot(Container1 &c1, Container2 &c2)//returns first element of c2 not present in c1
 	{

+ 46 - 5
hch/CArtHandler.cpp

@@ -12,6 +12,7 @@
 #include <boost/random/linear_congruential.hpp>
 #include <boost/algorithm/string/replace.hpp>
 #include "../lib/VCMI_Lib.h"
+#include "CSpellHandler.h"
 extern CLodHandler *bitmaph;
 using namespace boost::assign;
 
@@ -171,6 +172,10 @@ int CArtifact::getArtClassSerial() const
 	return -1;
 }
 
+std::string CArtifact::nodeName() const
+{
+	return "Artifact: " + Name();
+}
 // void CArtifact::getParents(TCNodes &out, const CBonusSystemNode *root /*= NULL*/) const
 // {
 // 	//combined artifact carries bonuses from its parts
@@ -199,7 +204,7 @@ CArtHandler::CArtHandler()
 
 CArtHandler::~CArtHandler()
 {
-	for (std::vector<CArtifact*>::iterator it = artifacts.begin(); it != artifacts.end(); ++it)
+	for (std::vector< ConstTransitivePtr<CArtifact> >::iterator it = artifacts.begin(); it != artifacts.end(); ++it)
 	{
 		delete (*it)->constituents;
 		delete (*it)->constituentOf;
@@ -436,7 +441,7 @@ void CArtHandler::erasePickedArt (si32 id)
 }
 ui16 CArtHandler::getRandomArt(int flags)
 {
-	std::vector<CArtifact*> out;
+	std::vector<ConstTransitivePtr<CArtifact> > out;
 	getAllowed(out, flags);
 	ui16 id = out[ran() % out.size()]->id;
 	erasePickedArt (id);
@@ -444,12 +449,12 @@ ui16 CArtHandler::getRandomArt(int flags)
 }
 ui16 CArtHandler::getArtSync (ui32 rand, int flags)
 {
-	std::vector<CArtifact*> out;
+	std::vector<ConstTransitivePtr<CArtifact> > out;
 	getAllowed(out, flags);
 	CArtifact *art = out[rand % out.size()];
 	return art->id;	
 }
-void CArtHandler::getAllowed(std::vector<CArtifact*> &out, int flags)
+void CArtHandler::getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags)
 {
 	if (flags & CArtifact::ART_TREASURE)
 		getAllowedArts (out, &treasures, CArtifact::ART_TREASURE);
@@ -465,7 +470,7 @@ void CArtHandler::getAllowed(std::vector<CArtifact*> &out, int flags)
 		std::fill_n (out.begin(), 64, artifacts[2]); //magic
 	}
 }
-void CArtHandler::getAllowedArts(std::vector<CArtifact*> &out, std::vector<CArtifact*> *arts, int flag)
+void CArtHandler::getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag)
 {
 	if (arts->empty()) //restock avaliable arts
 	{
@@ -854,3 +859,39 @@ void CArtHandler::initAllowedArtifactsList(const std::vector<ui8> &allowed)
 			allowedArtifacts.push_back(artifacts[i]);
 	}
 }
+
+CArtifactInstance::CArtifactInstance()
+{
+	init();
+}
+
+CArtifactInstance::CArtifactInstance( CArtifact *Art)
+{
+	init();
+	setType(Art);
+
+}
+
+void CArtifactInstance::setType( CArtifact *Art )
+{
+	art = Art;
+	attachTo(Art);
+}
+
+std::string CArtifactInstance::nodeName() const
+{
+	return "Artifact instance of " + (art ? art->Name() : std::string("uninitialized")) + " type";
+}
+
+CArtifactInstance * CArtifactInstance::createScroll( const CSpell *s)
+{
+	CArtifactInstance *ret = new CArtifactInstance(VLC->arth->artifacts[93]);
+	Bonus *b = new Bonus(Bonus::PERMANENT, Bonus::SPELL, Bonus::ARTIFACT_INSTANCE, -1, s->id	);
+	ret->addNewBonus(b);
+	return ret;
+}
+
+void CArtifactInstance::init()
+{
+	art = NULL;
+}

+ 28 - 5
hch/CArtHandler.h

@@ -4,8 +4,8 @@
 #include "../lib/HeroBonus.h"
 #include <set>
 #include <list>
-#include <string>
-#include <vector>
+
+#include "../lib/ConstTransitivePtr.h"
 
 /*
  * CArtHandler.h, part of VCMI engine
@@ -36,6 +36,7 @@ public:
 	virtual void SetProperty (int mod){};
 	virtual void Init(){};
 	int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
+	std::string nodeName() const OVERRIDE;
 
 	ui32 price;
 	std::vector<ui16> possibleSlots; //ids of slots where artifact can be placed
@@ -57,6 +58,28 @@ public:
 	//void getParents(TCNodes &out, const CBonusSystemNode *root = NULL) const;
 };
 
+class DLL_EXPORT CArtifactInstance : public CBonusSystemNode
+{
+public:
+	ConstTransitivePtr<CArtifact> art; 
+	si32 id; //id of the instance
+
+	CArtifactInstance();
+	CArtifactInstance(CArtifact *Art);
+
+	void init();
+	std::string nodeName() const OVERRIDE;
+	void setType(CArtifact *Art);
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & static_cast<CBonusSystemNode&>(*this);
+		h & art & id;
+	}
+
+	static CArtifactInstance *createScroll(const CSpell *s);
+};
+
 class DLL_EXPORT IModableArt : public CArtifact //artifact which can have different properties, such as scroll or banner
 { //used only for dynamic cast :P
 public:
@@ -118,7 +141,7 @@ class DLL_EXPORT CArtHandler //handles artifacts
 	void giveArtBonus(int aid, Bonus::BonusType type, int val, int subtype = -1, int valType = Bonus::BASE_NUMBER, ILimiter * limiter = NULL);
 public:
 	std::vector<CArtifact*> treasures, minors, majors, relics;
-	std::vector<CArtifact *> artifacts;
+	std::vector< ConstTransitivePtr<CArtifact> > artifacts;
 	std::vector<CArtifact *> allowedArtifacts;
 	std::set<ui32> bigArtifacts; // Artifacts that cannot be moved to backpack, e.g. war machines.
 	std::map<ui32, ui8> modableArtifacts; //1-scroll, 2-banner, 3-commander art with progressive bonus
@@ -130,8 +153,8 @@ public:
 	void clearHlpLists();
 	ui16 getRandomArt (int flags);
 	ui16 getArtSync (ui32 rand, int flags);
-	void getAllowedArts(std::vector<CArtifact*> &out, std::vector<CArtifact*> *arts, int flag);
-	void getAllowed(std::vector<CArtifact*> &out, int flags);
+	void getAllowedArts(std::vector<ConstTransitivePtr<CArtifact> > &out, std::vector<CArtifact*> *arts, int flag);
+	void getAllowed(std::vector<ConstTransitivePtr<CArtifact> > &out, int flags);
 	void erasePickedArt (si32 id);
 	bool isBigArtifact (ui32 artID) {return bigArtifacts.find(artID) != bigArtifacts.end();}
 	void equipArtifact (std::map<ui16, const CArtifact*> &artifWorn, ui16 slotID, const CArtifact* art);

+ 2 - 2
hch/CCreatureHandler.cpp

@@ -463,8 +463,8 @@ void CCreatureHandler::loadCreatures()
 	}
 	ifs.close();
 	ifs.clear();
-	for(i=1;i<=10;i++)
-		levelCreatures.insert(std::pair<int,std::vector<CCreature*> >(i,std::vector<CCreature*>()));
+	for(i = 1; i <= CRE_LEVELS; i++)
+		levelCreatures[i];
 
 	tlog5 << "\t\tReading config/monsters.txt" << std::endl;
 	ifs.open(DATA_DIR "/config/monsters.txt");

+ 6 - 5
hch/CCreatureHandler.h

@@ -10,6 +10,7 @@
 #include "../lib/HeroBonus.h"
 #include "../lib/CGameState.h"
 #include "../lib/CCreatureSet.h"
+#include "../lib/ConstTransitivePtr.h"
 
 /*
  * CCreatureHandler.h, part of VCMI engine
@@ -104,11 +105,11 @@ public:
 	CBonusSystemNode *globalEffects;
 	std::set<int> notUsedMonsters;
 	std::set<TCreature> doubledCreatures; //they get double week
-	std::vector<CCreature*> creatures; //creature ID -> creature info
-	std::map<int,std::vector<CCreature*> > levelCreatures; //level -> list of creatures
-	std::map<std::string,int> nameToID;
-	std::map<int,std::string> idToProjectile;
-	std::map<int,bool> idToProjectileSpin; //if true, appropriate projectile is spinning during flight
+	std::vector<ConstTransitivePtr<CCreature> > creatures; //creature ID -> creature info
+	bmap<int,std::vector<ConstTransitivePtr< CCreature> > > levelCreatures; //level -> list of creatures
+	bmap<std::string,int> nameToID;
+	bmap<int,std::string> idToProjectile;
+	bmap<int,bool> idToProjectileSpin; //if true, appropriate projectile is spinning during flight
 	std::vector<si8> factionAlignments; //1 for good, 0 for neutral and -1 for evil with faction ID as index
 	int factionToTurretCreature[F_NUMBER]; //which creature's animation should be used to dispaly creature in turret while siege
 

+ 3 - 1
hch/CHeroHandler.h

@@ -5,6 +5,8 @@
 #include <vector>
 #include <set>
 
+#include "../lib/ConstTransitivePtr.h"
+
 /*
  * CHeroHandler.h, part of VCMI engine
  *
@@ -118,7 +120,7 @@ const int PUZZLES_PER_FACTION = 48;
 class DLL_EXPORT CHeroHandler
 {
 public:
-	std::vector<CHero*> heroes; //changed from nodrze
+	std::vector< ConstTransitivePtr<CHero> > heroes; //changed from nodrze
 	std::vector<CHeroClass *> heroClasses;
 	std::vector<ui64> expPerLevel; //expPerLEvel[i] is amount of exp needed to reach level i; if it is not in this vector, multiplicate last value by 1,2 to get next value
 	

+ 3 - 3
hch/CMusicHandler.cpp

@@ -148,7 +148,7 @@ soundBase::soundID CSoundHandler::getSoundID(std::string &fileName)
 		return it->second;
 }
 
-void CSoundHandler::initCreaturesSounds(std::vector<CCreature*> &creatures)
+void CSoundHandler::initCreaturesSounds(std::vector<ConstTransitivePtr< CCreature> > &creatures)
 {
 	tlog5 << "\t\tReading config/cr_sounds.txt" << std::endl;
 	std::ifstream ifs(DATA_DIR "/config/cr_sounds.txt");
@@ -172,7 +172,7 @@ void CSoundHandler::initCreaturesSounds(std::vector<CCreature*> &creatures)
 		{
 			int id = -1;
 
-			std::map<std::string,int>::iterator i = CGI->creh->nameToID.find(cname);
+			bmap<std::string,int>::const_iterator i = CGI->creh->nameToID.find(cname);
 			if(i != CGI->creh->nameToID.end())
 				id = i->second;
 			else
@@ -238,7 +238,7 @@ void CSoundHandler::initSpellsSounds(std::vector<CSpell> &spells)
 
 		if (str.good() || (str.eof() && soundfile != ""))
 		{
-			CSpell &s = CGI->spellh->spells[spellid];
+			const CSpell &s = CGI->spellh->spells[spellid];
 
 			if (s.soundID != soundBase::invalid)
 				tlog1 << "Spell << " << spellid << " already has a sound" << std::endl;

+ 1 - 1
hch/CMusicHandler.h

@@ -80,7 +80,7 @@ public:
 	void init();
 	void release();
 
-	void initCreaturesSounds(std::vector<CCreature*> &creatures);
+	void initCreaturesSounds(std::vector<ConstTransitivePtr<CCreature> > &creatures);
 	void initSpellsSounds(std::vector<CSpell> &spells);
 	void setVolume(unsigned int percent);
 

+ 14 - 11
hch/CObjectHandler.cpp

@@ -1105,7 +1105,7 @@ void CGHeroInstance::initObj()
 				break;
 			case 9://upgrade creatures
 			{
-				std::vector<CCreature*>* creatures = &VLC->creh->creatures;
+				std::vector< ConstTransitivePtr<CCreature> >* creatures = &VLC->creh->creatures;
 				bonus->type = Bonus::SPECIAL_UPGRADE;
 				bonus->subtype = it->subtype; //base id
 				bonus->additionalInfo = it->additionalinfo; //target id
@@ -1161,7 +1161,7 @@ void CGHeroInstance::UpdateSpeciality()
 {
 	if (speciality.growthsWithLevel)
 	{
-		std::vector<CCreature*>* creatures = &VLC->creh->creatures;
+		std::vector< ConstTransitivePtr<CCreature> > & creatures = VLC->creh->creatures;
 
 		BOOST_FOREACH(Bonus *it, speciality.bonuses)
 		{
@@ -1171,14 +1171,14 @@ void CGHeroInstance::UpdateSpeciality()
 					it->val = (speciality.valOfBonuses(Bonus::SPECIAL_SECONDARY_SKILL, it->subtype) * level);
 					break; //use only hero skills as bonuses to avoid feedback loop
 				case Bonus::PRIMARY_SKILL: //for crearures, that is
-					int creLevel = (*creatures)[it->additionalInfo]->level;
+					int creLevel = creatures[it->additionalInfo]->level;
 					if(!creLevel)
 					{
 						if(it->additionalInfo == 146)
 							creLevel = 5; //treat ballista as 5-level
 						else
 						{
-							tlog2 << "Warning: unknown level of " << (*creatures)[it->additionalInfo]->namePl << std::endl;
+							tlog2 << "Warning: unknown level of " << creatures[it->additionalInfo]->namePl << std::endl;
 							continue;
 						}
 					}
@@ -1188,10 +1188,10 @@ void CGHeroInstance::UpdateSpeciality()
 					switch (it->subtype)
 					{
 						case PrimarySkill::ATTACK:
-							param = (*creatures)[it->additionalInfo]->attack;
+							param = creatures[it->additionalInfo]->attack;
 							break;
 						case PrimarySkill::DEFENSE:
-							param = (*creatures)[it->additionalInfo]->defence;
+							param = creatures[it->additionalInfo]->defence;
 							break;
 					}
 					it->val = ceil(param * (1 + primSkillModifier)) - param; //yep, overcomplicated but matches original
@@ -3014,7 +3014,7 @@ int CGCreature::takenAction(const CGHeroInstance *h, bool allowJoin) const
 		std::set<ui32> myKindCres; //what creatures are the same kind as we
 		myKindCres.insert(subID); //we
 		myKindCres.insert(VLC->creh->creatures[subID]->upgrades.begin(),VLC->creh->creatures[subID]->upgrades.end()); //our upgrades
-		for(std::vector<CCreature*>::iterator i=VLC->creh->creatures.begin(); i!=VLC->creh->creatures.end(); i++)
+		for(std::vector<ConstTransitivePtr<CCreature> >::iterator i=VLC->creh->creatures.begin(); i!=VLC->creh->creatures.end(); i++)
 			if(vstd::contains((*i)->upgrades, (ui32) id)) //it's our base creatures
 				myKindCres.insert((*i)->idNumber);
 
@@ -3616,9 +3616,12 @@ void CGArtifact::onHeroVisit( const CGHeroInstance * h ) const
 			}
 			break;
 			case 93:
-				iw.components.push_back (Component(Component::SPELL, spell,0,0));
-				iw.text.addTxt (MetaString::ADVOB_TXT,135);
-				iw.text.addReplacement(MetaString::SPELL_NAME, spell);
+				{
+					int spellID = art->getBonus(Selector::type(Bonus::SPELL))->subtype;
+					iw.components.push_back (Component(Component::SPELL, spellID,0,0));
+					iw.text.addTxt (MetaString::ADVOB_TXT,135);
+					iw.text.addReplacement(MetaString::SPELL_NAME, spellID);
+				}
 			break;
 
 		}
@@ -3648,7 +3651,7 @@ void CGArtifact::pick(const CGHeroInstance * h) const
 		if (ID == 93) //scroll
 		{
 			NewArtifact na;
-			na.value = spell;
+			//na.value = spell;
 			na.artid = subID;
 			cb->sendAndApply(&na);
 			cb->giveNewArtifact(h->id, -2);

+ 8 - 2
hch/CObjectHandler.h

@@ -23,6 +23,7 @@
  *
  */
 
+class CArtifactInstance;
 struct MetaString;
 struct BattleInfo;
 class IGameCallback;
@@ -266,6 +267,10 @@ public:
 	ui8 inTownGarrison; // if hero is in town garrison 
 	const CGTownInstance * visitedTown; //set if hero is visiting town or in the town garrison
 	const CGBoat *boat; //set to CGBoat when sailing
+	
+	std::vector<const CArtifactInstance*> gartifacts; //hero's artifacts from bag
+	std::map<ui16, const CArtifactInstance*> gartifWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
+
 	std::vector<const CArtifact*> artifacts; //hero's artifacts from bag
 	std::map<ui16, const CArtifact*> artifWorn; //map<position,artifact_id>; positions: 0 - head; 1 - shoulders; 2 - neck; 3 - right hand; 4 - left hand; 5 - torso; 6 - right ring; 7 - left ring; 8 - feet; 9 - misc1; 10 - misc2; 11 - misc3; 12 - misc4; 13 - mach1; 14 - mach2; 15 - mach3; 16 - mach4; 17 - spellbook; 18 - misc5
 	std::set<ui32> spells; //known spells (spell IDs)
@@ -764,8 +769,9 @@ public:
 class DLL_EXPORT CGArtifact : public CArmedInstance
 {
 public:
+	CArtifactInstance *art;
+
 	std::string message;
-	ui32 spell; //if it's spell scroll
 	void onHeroVisit(const CGHeroInstance * h) const;
 	void fightForArt(ui32 agreed, const CGHeroInstance *h) const;
 	void endBattle(BattleResult *result, const CGHeroInstance *h) const;
@@ -775,7 +781,7 @@ public:
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
 		h & static_cast<CArmedInstance&>(*this);
-		h & message & spell;
+		h & message & art;
 	}
 };
 

+ 1 - 1
hch/CSpellHandler.h

@@ -41,7 +41,7 @@ public:
 	std::vector<std::string> range; //description of spell's range in SRSL by magic school level
 	std::set<ui16> rangeInHexes(unsigned int centralHex, ui8 schoolLvl ) const; //convert range to specific hexes
 	si16 mainEffectAnim; //main spell effect animation, in AC format (or -1 when none)
-	soundBase::soundID soundID;	// spell sound id
+	mutable soundBase::soundID soundID;	// spell sound id
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{

+ 8 - 8
lib/CGameState.cpp

@@ -1157,7 +1157,7 @@ CGHeroInstance *CGameState::getHero(int objid)
 {
 	if(objid<0 || objid>=map->objects.size() || map->objects[objid]->ID!=HEROI_TYPE)
 		return NULL;
-	return static_cast<CGHeroInstance *>(map->objects[objid]);
+	return static_cast<CGHeroInstance *>(+map->objects[objid]);
 }
 
 const CGHeroInstance * CGameState::getHero( int objid ) const
@@ -1247,13 +1247,13 @@ std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
 			{
 				for(unsigned int i=0;i<map->objects.size();i++)
 				{
-					if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
+					if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(+map->objects[i])->identifier == info->identifier)
 					{
 						randomizeObject(map->objects[i]); //we have to randomize the castle first
 						faction = map->objects[i]->subID;
 						break;
 					}
-					else if(map->objects[i]->ID==TOWNI_TYPE && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
+					else if(map->objects[i]->ID==TOWNI_TYPE && dynamic_cast<CGTownInstance*>(+map->objects[i])->identifier == info->identifier)
 					{
 						faction = map->objects[i]->subID;
 						break;
@@ -1288,13 +1288,13 @@ std::pair<int,int> CGameState::pickObject (CGObjectInstance *obj)
 			{
 				for(unsigned int i=0;i<map->objects.size();i++)
 				{
-					if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
+					if(map->objects[i]->ID==77 && dynamic_cast<CGTownInstance*>(+map->objects[i])->identifier == info->identifier)
 					{
 						randomizeObject(map->objects[i]); //we have to randomize the castle first
 						faction = map->objects[i]->subID;
 						break;
 					}
-					else if(map->objects[i]->ID==TOWNI_TYPE && dynamic_cast<CGTownInstance*>(map->objects[i])->identifier == info->identifier)
+					else if(map->objects[i]->ID==TOWNI_TYPE && dynamic_cast<CGTownInstance*>(+map->objects[i])->identifier == info->identifier)
 					{
 						faction = map->objects[i]->subID;
 						break;
@@ -2180,7 +2180,7 @@ void CGameState::init( StartInfo * si, ui32 checksum, int Seed )
 	{
 		map->objects[i]->initObj();
 		if(map->objects[i]->ID == 62) //prison also needs to initialize hero
-			static_cast<CGHeroInstance*>(map->objects[i])->initHero();
+			static_cast<CGHeroInstance*>(+map->objects[i])->initHero();
 	}
 	CGTeleport::postInit(); //pairing subterranean gates
 }
@@ -2242,7 +2242,7 @@ int CGameState::battleGetBattlefieldType(int3 tile)
 	if(dynamic_cast<const CGMine *>(t.visitableObjects.front()))
 		return 12;
 
-	const std::vector <CGObjectInstance*> & objs = map->objects;
+	const std::vector <ConstTransitivePtr<CGObjectInstance> > & objs = map->objects;
 	for(int g=0; g<objs.size(); ++g)
 	{
 		if( !objs[g] || objs[g]->pos.x - tile.x < 0  ||  objs[g]->pos.x - tile.x >= 8  
@@ -3789,7 +3789,7 @@ int CGameState::victoryCheck( ui8 player ) const
 					const CArmedInstance *ai = NULL;
 					if(map->objects[i] 
 						&& map->objects[i]->tempOwner == player //object controlled by player
-						&&  (ai = dynamic_cast<const CArmedInstance*>(map->objects[i]))) //contains army
+						&&  (ai = dynamic_cast<const CArmedInstance*>(+map->objects[i]))) //contains army
 					{
 						for(TSlots::const_iterator i=ai->Slots().begin(); i!=ai->Slots().end(); ++i) //iterate through army
 							if(i->second->type->idNumber == map->victoryCondition.ID) //it's searched creature

+ 1 - 1
lib/Connection.cpp

@@ -405,6 +405,6 @@ void CSerializer::addStdVecItems(CGameState *gs, LibClasses *lib)
 	registerVectoredType(&lib->heroh->heroes, &CHero::ID);
 	registerVectoredType(&lib->creh->creatures, &CCreature::idNumber);
 	registerVectoredType(&lib->arth->artifacts, &CArtifact::id);
-	registerVectoredType(&gs->map->artInstances, &IModableArt::ID);
+	registerVectoredType(&gs->map->artInstances, &CArtifactInstance::id);
 	smartVectorMembersSerialization = true;
 }

+ 10 - 3
lib/Connection.h

@@ -23,6 +23,8 @@
 #include <boost/mpl/identity.hpp>
 #include <boost/any.hpp>
 
+#include "ConstTransitivePtr.h"
+
 const ui32 version = 727;
 class CConnection;
 class CGObjectInstance;
@@ -232,10 +234,10 @@ struct SerializationLevel
 template <typename T>
 struct VectorisedObjectInfo
 {
-	const std::vector<T*> *vector;	//pointer to the appropriate vector
+	const std::vector<ConstTransitivePtr<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)
+	VectorisedObjectInfo(const std::vector< ConstTransitivePtr<T> > *Vector, const si32 T::*IdPtr)
 		:vector(Vector), idPtr(IdPtr)
 	{
 	}
@@ -259,6 +261,11 @@ public:
 	{
 		vectors[&typeid(T)] = VectorisedObjectInfo<T>(Vector, IdPtr);
 	}
+	template <typename T>
+	void registerVectoredType(const std::vector<ConstTransitivePtr<T> > *Vector, const si32 T::*IdPtr)
+	{
+		vectors[&typeid(T)] = VectorisedObjectInfo<T>(Vector, IdPtr);
+	}
 
 	template <typename T>
 	const VectorisedObjectInfo<T> *getVectorisedTypeInfo()
@@ -290,7 +297,7 @@ public:
 
 		assert(oInfo.vector);
 		assert(oInfo.vector->size() > id);
-		return (*oInfo.vector)[id];
+		return const_cast<T*>(+(*oInfo.vector)[id]);
 	}
 
 	template <typename T>

+ 16 - 0
lib/ConstTransitivePtr.h

@@ -9,10 +9,26 @@ public:
 		: ptr(Ptr) 
 	{}
 
+	const T& operator*() const
+	{
+		return *ptr;
+	}
+	T& operator*()
+	{
+		return *ptr;
+	}
 	operator const T*() const
 	{
 		return ptr;
 	}
+	T* operator+()
+	{
+		return ptr;
+	}
+	const T* operator+() const
+	{
+		return ptr;
+	}
 	operator T*() 
 	{
 		return ptr;

+ 5 - 0
lib/HeroBonus.cpp

@@ -164,6 +164,11 @@ Bonus * CBonusSystemNode::getBonus(const CSelector &selector)
 	return NULL;
 }
 
+const Bonus * CBonusSystemNode::getBonus( const CSelector &selector ) const
+{
+	return (const_cast<CBonusSystemNode*>(this))->getBonus(selector);
+}
+
 void CBonusSystemNode::getModifiersWDescr(TModDescr &out, Bonus::BonusType type, int subtype /*= -1 */) const
 {
 	getModifiersWDescr(out, Selector::typeSybtype(type, subtype));

+ 2 - 0
lib/HeroBonus.h

@@ -184,6 +184,7 @@ struct DLL_EXPORT Bonus
 	enum BonusSource
 	{
 		ARTIFACT, 
+		ARTIFACT_INSTANCE, 
 		OBJECT, 
 		CASTED_SPELL,
 		CREATURE_ABILITY,
@@ -404,6 +405,7 @@ public:
 	ui16 MaxHealth() const; //get max HP of stack with all modifiers
 
 
+	const Bonus *getBonus(const CSelector &selector) const;
 	//non-const interface
 	void getParents(TNodes &out);  //retrieves list of parent nodes (nodes to inherit bonuses from), source is the prinary asker
 	Bonus *getBonus(const CSelector &selector);

+ 1 - 1
lib/IGameCallback.cpp

@@ -54,7 +54,7 @@ const CGTownInstance* IGameCallback::getTown(int objid)
 {
 	const CGObjectInstance *obj = getObj(objid, false);
 	if(obj)
-		return dynamic_cast<const CGTownInstance*>(gs->map->objects[objid]);
+		return dynamic_cast<const CGTownInstance*>(+gs->map->objects[objid]);
 	else
 		return NULL;
 }

+ 24 - 24
lib/NetPacksLib.cpp

@@ -413,7 +413,7 @@ DLL_EXPORT void RazeStructures::applyGs( CGameState *gs )
 }
 DLL_EXPORT void SetAvailableCreatures::applyGs( CGameState *gs )
 {
-	CGDwelling *dw = dynamic_cast<CGDwelling*>(gs->map->objects[tid]);
+	CGDwelling *dw = dynamic_cast<CGDwelling*>(+gs->map->objects[tid]);
 	assert(dw);
 	dw->creatures = creatures;
 }
@@ -581,28 +581,28 @@ DLL_EXPORT void NewObject::applyGs( CGameState *gs )
 }
 DLL_EXPORT void NewArtifact::applyGs( CGameState *gs )
 {
-	IModableArt * art;
-
-	std::map<ui32,ui8>::iterator itr = VLC->arth->modableArtifacts.find(artid);
-	switch (itr->second)
-	{
-			case 1:
-				art = new CScroll;
-				break;
-			case 2:
-				art = new CCustomizableArt;
-				break;
-			case 3:
-				art = new CCommanderArt;
-				break;
-			default:
-				tlog1<<"unhandled customizable artifact!\n";
-	};
-	*art = *static_cast<IModableArt*>(VLC->arth->artifacts[artid]); //copy properties
-	art->ID = gs->map->artInstances.size();
-	art->SetProperty (value); //init scroll, banner, commander art
-	art->Init(); //set bonuses for new instance
-	gs->map->artInstances.push_back(art);
+// 	IModableArt * art;
+// 
+// 	std::map<ui32,ui8>::iterator itr = VLC->arth->modableArtifacts.find(artid);
+// 	switch (itr->second)
+// 	{
+// 			case 1:
+// 				art = new CScroll;
+// 				break;
+// 			case 2:
+// 				art = new CCustomizableArt;
+// 				break;
+// 			case 3:
+// 				art = new CCommanderArt;
+// 				break;
+// 			default:
+// 				tlog1<<"unhandled customizable artifact!\n";
+// 	};
+// 	*art = *static_cast<IModableArt*>(+VLC->arth->artifacts[artid]); //copy properties
+// 	art->ID = gs->map->artInstances.size();
+// 	art->SetProperty (value); //init scroll, banner, commander art
+// 	art->Init(); //set bonuses for new instance
+// 	gs->map->artInstances.push_back(art);
 }
 
 DLL_EXPORT const CStackInstance * StackLocation::getStack()
@@ -687,7 +687,7 @@ DLL_EXPORT void SetAvailableArtifacts::applyGs( CGameState *gs )
 {
 	if(id >= 0)
 	{
-		if(CGBlackMarket *bm = dynamic_cast<CGBlackMarket*>(gs->map->objects[id]))
+		if(CGBlackMarket *bm = dynamic_cast<CGBlackMarket*>(+gs->map->objects[id]))
 		{
 			bm->artifacts = arts;
 		}

+ 21 - 1
lib/map.cpp

@@ -11,6 +11,7 @@
 #include "../hch/CCreatureHandler.h"
 #include <boost/bind.hpp>
 #include <assert.h>
+#include "../hch/CSpellHandler.h"
 
 /*
  * map.cpp, part of VCMI engine
@@ -1558,11 +1559,24 @@ void Mapa::readObjects( const unsigned char * bufor, int &i)
 					}
 					i+=4;
 				}
+
+				CArtifactInstance *innerArt = NULL;
 				if(defInfo->id==93)
 				{
-					art->spell = readNormalNr(bufor,i); 
+					int spellID = readNormalNr(bufor,i); 
 					i+=4;
+					innerArt = CArtifactInstance::createScroll(&VLC->spellh->spells[spellID]);
+				}
+				else if(art->ID == 5) //specific artifact
+				{
+					innerArt = new CArtifactInstance(VLC->arth->artifacts[art->subID]);
 				}
+				else
+				{
+					innerArt = new CArtifactInstance();
+				}
+				art->art = innerArt;
+				addNewArtifactInstance(innerArt);
 				break;
 			}
 		case 76: case 79: //random resource; resource
@@ -2087,6 +2101,12 @@ void Mapa::checkForObjectives()
 	}
 }
 
+void Mapa::addNewArtifactInstance( CArtifactInstance *art )
+{
+	art->id = artInstances.size();
+	artInstances.push_back(art);
+}
+
 LossCondition::LossCondition()
 {
 	obj = NULL;

+ 8 - 5
lib/map.h

@@ -14,6 +14,8 @@
 #include "../hch/CDefObjInfoHandler.h"
 #endif
 
+#include "ConstTransitivePtr.h"
+
 /*
  * map.h, part of VCMI engine
  *
@@ -24,6 +26,7 @@
  *
  */
 
+class CArtifactInstance;
 class CGDefInfo;
 class CGObjectInstance;
 class CGHeroInstance;
@@ -276,10 +279,10 @@ struct DLL_EXPORT Mapa : public CMapHeader
 	int3 grailPos;
 	int grailRadious;
 
-	std::vector<CGObjectInstance*> objects;
+	std::vector< ConstTransitivePtr<CGObjectInstance> > objects;
 	std::vector<CGHeroInstance*> heroes;
 	std::vector<CGTownInstance*> towns;
-	std::vector<IModableArt *> artInstances; //stores single scrolls
+	std::vector< ConstTransitivePtr<CArtifactInstance> > artInstances; //stores all artifacts
 	std::map<ui16, CGCreature*> monsters;
 	std::map<ui16, CGHeroInstance*> heroesToBeat;
 
@@ -298,7 +301,7 @@ struct DLL_EXPORT Mapa : public CMapHeader
 	int loadSeerHut( const unsigned char * bufor, int i, CGObjectInstance *& nobj);
 
 	void checkForObjectives();
-
+	void addNewArtifactInstance(CArtifactInstance *art);
 	void addBlockVisTiles(CGObjectInstance * obj);
 	void removeBlockVisTiles(CGObjectInstance * obj, bool total=false);
 	Mapa(std::string filename); //creates map structure from .h3m file
@@ -411,9 +414,9 @@ struct DLL_EXPORT Mapa : public CMapHeader
 			{
 				if(!objects[i]) continue;
 				if(objects[i]->ID == HEROI_TYPE)
-					heroes.push_back(static_cast<CGHeroInstance*>(objects[i]));
+					heroes.push_back(static_cast<CGHeroInstance*>(+objects[i]));
 				else if(objects[i]->ID == TOWNI_TYPE)
-					towns.push_back(static_cast<CGTownInstance*>(objects[i]));
+					towns.push_back(static_cast<CGTownInstance*>(+objects[i]));
 
 				addBlockVisTiles(objects[i]); //recreate blockvis map
 			}

+ 1 - 1
nodrze.h

@@ -126,7 +126,7 @@ public:
 	bool operator+=(T * co); //add
 	bool operator+=(T co); //add
 	bool operator-=(T co); //remove
-	bool operator-=(T * co); //remove
+	bool operator-=(T * co); //ve
 	T* operator%(T * co); // search and return pointer
 	bool operator&(T co); // check if exist
 	bool operator&(T * co); // check if exist

+ 53 - 53
server/CGameHandler.cpp

@@ -199,7 +199,7 @@ void CGameHandler::levelUpHero(int ID, int skill)
 
 void CGameHandler::levelUpHero(int ID)
 {
-	CGHeroInstance *hero = static_cast<CGHeroInstance *>(gs->map->objects[ID]);
+	CGHeroInstance *hero = static_cast<CGHeroInstance *>(+gs->map->objects[ID]);
 	if (hero->exp < VLC->heroh->reqExp(hero->level+1)) // no more level-ups
 		return;
 		
@@ -2198,49 +2198,49 @@ void CGameHandler::giveHeroArtifact(int artid, int hid, int position) //pos==-1
 }
 void CGameHandler::giveNewArtifact(int hid, int position)
 {
-	const CGHeroInstance* h = getHero(hid);
-	CArtifact * art = gs->map->artInstances.back(); //we use it only to immediatelly equip new artifact
-
-	SetHeroArtifacts sha;
-	sha.hid = hid;
-	sha.artifacts = h->artifacts;
-	sha.artifWorn = h->artifWorn;
-
-	if(position<0)
-	{
-		if(position == -2)
-		{
-			int i;
-			for(i=0; i<art->possibleSlots.size(); i++) //try to put artifact into first available slot
-			{
-				if( !vstd::contains(sha.artifWorn, art->possibleSlots[i]) )
-				{
-					//we've found a free suitable slot
-					VLC->arth->equipArtifact(sha.artifWorn, art->possibleSlots[i], art);
-					break;
-				}
-			}
-			if(i == art->possibleSlots.size() && !art->isBig()) //if haven't find proper slot, use backpack or discard big artifact
-				sha.artifacts.push_back(art);
-		}
-		else if (!art->isBig()) //should be -1 => put artifact into backpack
-		{
-			sha.artifacts.push_back(art);
-		}
-	}
-	else
-	{
-		if(!vstd::contains(sha.artifWorn,ui16(position)))
-		{
-			VLC->arth->equipArtifact(sha.artifWorn, position, art);
-		}
-		else if (!art->isBig())
-		{
-			sha.artifacts.push_back(art);
-		}
-	}
-
-	sendAndApply(&sha);
+// 	const CGHeroInstance* h = getHero(hid);
+// 	CArtifact * art = gs->map->artInstances.back(); //we use it only to immediatelly equip new artifact
+// 
+// 	SetHeroArtifacts sha;
+// 	sha.hid = hid;
+// 	sha.artifacts = h->artifacts;
+// 	sha.artifWorn = h->artifWorn;
+// 
+// 	if(position<0)
+// 	{
+// 		if(position == -2)
+// 		{
+// 			int i;
+// 			for(i=0; i<art->possibleSlots.size(); i++) //try to put artifact into first available slot
+// 			{
+// 				if( !vstd::contains(sha.artifWorn, art->possibleSlots[i]) )
+// 				{
+// 					//we've found a free suitable slot
+// 					VLC->arth->equipArtifact(sha.artifWorn, art->possibleSlots[i], art);
+// 					break;
+// 				}
+// 			}
+// 			if(i == art->possibleSlots.size() && !art->isBig()) //if haven't find proper slot, use backpack or discard big artifact
+// 				sha.artifacts.push_back(art);
+// 		}
+// 		else if (!art->isBig()) //should be -1 => put artifact into backpack
+// 		{
+// 			sha.artifacts.push_back(art);
+// 		}
+// 	}
+// 	else
+// 	{
+// 		if(!vstd::contains(sha.artifWorn,ui16(position)))
+// 		{
+// 			VLC->arth->equipArtifact(sha.artifWorn, position, art);
+// 		}
+// 		else if (!art->isBig())
+// 		{
+// 			sha.artifacts.push_back(art);
+// 		}
+// 	}
+// 
+// 	sendAndApply(&sha);
 }
 bool CGameHandler::removeArtifact(const CArtifact* art, int hid)
 {
@@ -2585,8 +2585,8 @@ void CGameHandler::close()
 
 bool CGameHandler::arrangeStacks( si32 id1, si32 id2, ui8 what, ui8 p1, ui8 p2, si32 val, ui8 player )
 {
-	CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id1]),
-		*s2 = static_cast<CArmedInstance*>(gs->map->objects[id2]);
+	CArmedInstance *s1 = static_cast<CArmedInstance*>(+gs->map->objects[id1]),
+		*s2 = static_cast<CArmedInstance*>(+gs->map->objects[id2]);
 	CCreatureSet &S1 = *s1, &S2 = *s2;
 	StackLocation sl1(s1, p1), sl2(s2, p2);
 
@@ -2688,7 +2688,7 @@ int CGameHandler::getPlayerAt( CConnection *c ) const
 
 bool CGameHandler::disbandCreature( si32 id, ui8 pos )
 {
-	CArmedInstance *s1 = static_cast<CArmedInstance*>(gs->map->objects[id]);
+	CArmedInstance *s1 = static_cast<CArmedInstance*>(+gs->map->objects[id]);
 	if(!vstd::contains(s1->slots,pos))
 	{
 		complain("Illegal call to disbandCreature - no such stack in army!");
@@ -2701,7 +2701,7 @@ bool CGameHandler::disbandCreature( si32 id, ui8 pos )
 
 bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
 {
-	CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid]);
+	CGTownInstance * t = static_cast<CGTownInstance*>(+gs->map->objects[tid]);
 	CBuilding * b = VLC->buildh->buildings[t->subID][bid];
 
 	if( !force && gs->canBuildStructure(t,bid) != 7)
@@ -2811,7 +2811,7 @@ bool CGameHandler::buildStructure( si32 tid, si32 bid, bool force /*=false*/ )
 bool CGameHandler::razeStructure (si32 tid, si32 bid)
 {
 ///incomplete, simply erases target building
-	CGTownInstance * t = static_cast<CGTownInstance*>(gs->map->objects[tid]);
+	CGTownInstance * t = static_cast<CGTownInstance*>(+gs->map->objects[tid]);
 	if (t->builtBuildings.find(bid) == t->builtBuildings.end())
 		return false;
 	RazeStructures rs;
@@ -2840,7 +2840,7 @@ void CGameHandler::sendMessageToAll( const std::string &message )
 
 bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 fromLvl )
 {
-	const CGDwelling *dw = static_cast<CGDwelling*>(gs->map->objects[objid]);
+	const CGDwelling *dw = static_cast<CGDwelling*>(+gs->map->objects[objid]);
 	const CArmedInstance *dst = NULL;
 	const CCreature *c = VLC->creh->creatures[crid];
 	bool warMachine = c->hasBonusOfType(Bonus::SIEGE_WEAPON);
@@ -2929,7 +2929,7 @@ bool CGameHandler::recruitCreatures( si32 objid, ui32 crid, ui32 cram, si32 from
 
 bool CGameHandler::upgradeCreature( ui32 objid, ui8 pos, ui32 upgID )
 {
-	CArmedInstance *obj = static_cast<CArmedInstance*>(gs->map->objects[objid]);
+	CArmedInstance *obj = static_cast<CArmedInstance*>(+gs->map->objects[objid]);
 	assert(obj->hasStackAtSlot(pos));
 	UpgradeInfo ui = gs->getUpgradeInfo(obj->getStack(pos));
 	int player = obj->tempOwner;
@@ -4704,7 +4704,7 @@ void CGameHandler::checkLossVictory( ui8 player )
 		for (std::vector<CGHeroInstance*>::const_iterator i = hlp.begin(); i != hlp.end(); i++) //eliminate heroes
 			removeObject((*i)->id);
 
-		for (std::vector<CGObjectInstance*>::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
+		for (std::vector<ConstTransitivePtr<CGObjectInstance> >::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
 		{
 			if(*i  &&  (*i)->tempOwner == player)
 				setOwner((**i).id,NEUTRAL_PLAYER);
@@ -4848,7 +4848,7 @@ void CGameHandler::getLossVicMessage( ui8 player, ui8 standard, bool victory, In
 
 bool CGameHandler::dig( const CGHeroInstance *h )
 {
-	for (std::vector<CGObjectInstance*>::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
+	for (std::vector<ConstTransitivePtr<CGObjectInstance> >::const_iterator i = gs->map->objects.begin(); i != gs->map->objects.end(); i++) //unflag objs
 	{
 		if(*i && (*i)->ID == 124  &&  (*i)->pos == h->getPosition())
 		{