Răsfoiți Sursa

Partial fix for 37. Full fix for 27, 64, 600. Fix for bug where code tried to reload non existent file.

ori.bar 14 ani în urmă
părinte
comite
5b836f428a

+ 87 - 45
client/CAdvmapInterface.cpp

@@ -56,7 +56,7 @@ using namespace CSDL_Ext;
 
 CAdvMapInt *adventureInt;
 
-CMinimap::CMinimap(bool draw)
+CMinimap::CMinimap()
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	used = LCLICK | RCLICK | HOVER;
@@ -93,39 +93,29 @@ CMinimap::CMinimap(bool draw)
 		vinya.second.unused = 255;
 		colorsBlocked.insert(vinya);
 	}
-
-	if (draw)
-		redraw();
 }
 
 CMinimap::~CMinimap()
 {
 	SDL_FreeSurface(temps);
-	
-	for(int g=0; g<map.size(); ++g)
-		SDL_FreeSurface(map[g]);
-	map.clear();
-
-	for(int g=0; g<FoW.size(); ++g)
-		SDL_FreeSurface(FoW[g]);
-	FoW.clear();
-
-	for(int g=0; g<flObjs.size(); ++g)
-		SDL_FreeSurface(flObjs[g]);
-	flObjs.clear();
+	for (std::map<int, CMinimapSurfacesRef>::iterator it = surfs.begin(); it != surfs.end(); ++it)
+	{
+		it->second.free();
+	}
 }
 
 void CMinimap::draw(SDL_Surface * to)
 {
+	int player = adventureInt->player;
 	if(LOCPLINT->makingTurn)
 	{
 		int3 mapSizes = LOCPLINT->cb->getMapSize();
 		//draw terrain
-		blitAt(map[adventureInt->position.z],0,0,temps);
+		blitAt(surfs[player].map()[adventureInt->position.z],0,0,temps);
 
 		//draw heroes
 		std::vector <const CGHeroInstance *> hh = LOCPLINT->cb->getHeroesInfo(false);
-		int mw = map[0]->w, mh = map[0]->h,
+		int mw = surfs[player].map()[0]->w, mh = surfs[player].map()[0]->h,
 			wo = mw/mapSizes.x, ho = mh/mapSizes.y;
 
 		for (size_t i=0; i < hh.size(); ++i)
@@ -145,9 +135,9 @@ void CMinimap::draw(SDL_Surface * to)
 			}
 		}
 
-		blitAt(flObjs[adventureInt->position.z],0,0,temps);
+		blitAt(surfs[player].flObjs()[adventureInt->position.z],0,0,temps);
 
-		blitAt(FoW[adventureInt->position.z],0,0,temps);
+		blitAt(surfs[player].FoW()[adventureInt->position.z],0,0,temps);
 
 		//draw radar
 		const int tilesw=(ADVOPT.advmapW+31)/32;
@@ -167,8 +157,15 @@ void CMinimap::draw(SDL_Surface * to)
 		aiShield->showAll(to);
 	}
 }
-void CMinimap::redraw(int level)// (level==-1) => redraw all levels
+
+CMinimapSurfacesRef::CMinimapSurfacesRef() : ready(false)
 {
+}
+
+
+void CMinimapSurfacesRef::redraw(int level)
+{
+	ready = true;
 	initMap(level);
 
 	//FoW
@@ -181,29 +178,31 @@ void CMinimap::redraw(int level)// (level==-1) => redraw all levels
 	showVisibleTiles();
 }
 
-void CMinimap::initMap(int level)
+void CMinimapSurfacesRef::initMap(int level)
 {
 	/*for(int g=0; g<map.size(); ++g)
 	{
 		SDL_FreeSurface(map[g]);
 	}
 	map.clear();*/
-
+	const Rect &minimap_pos = adventureInt->minimap.pos;
+	std::map<int,SDL_Color> &colors = adventureInt->minimap.colors;
+	std::map<int,SDL_Color> &colorsBlocked = adventureInt->minimap.colorsBlocked;
 	int3 mapSizes = LOCPLINT->cb->getMapSize();
 	for (size_t i=0; i<CGI->mh->sizes.z; i++)
 	{
-		SDL_Surface * pom ;
+		SDL_Surface *pom;
 		if ((level>=0) && (i!=level))
 			continue;
-		if (map.size()<i+1)
-			pom = CSDL_Ext::newSurface(pos.w,pos.h,screen);
-		else pom = map[i];
-		for (int x=0;x<pos.w;x++)
+		if (map_.size()<i+1)
+			pom = CSDL_Ext::newSurface(minimap_pos.w,minimap_pos.h,screen);
+		else pom = map_[i];
+		for (int x=0;x<minimap_pos.w;x++)
 		{
-			for (int y=0;y<pos.h;y++)
+			for (int y=0;y<minimap_pos.h;y++)
 			{
-				int mx=(mapSizes.x*x)/pos.w;
-				int my=(mapSizes.y*y)/pos.h;
+				int mx=(mapSizes.x*x)/minimap_pos.w;
+				int my=(mapSizes.y*y)/minimap_pos.h;
 				const TerrainTile * tile = LOCPLINT->cb->getTile(int3(mx, my, i), false);
 				if(tile)
 				{
@@ -213,12 +212,12 @@ void CMinimap::initMap(int level)
 				}
 			}
 		}
-		map.push_back(pom);
+		map_.push_back(pom);
 
 	}
 }
 
-void CMinimap::initFoW(int level)
+void CMinimapSurfacesRef::initFoW(int level)
 {
 	/*for(int g=0; g<FoW.size(); ++g)
 	{
@@ -226,14 +225,15 @@ void CMinimap::initFoW(int level)
 	}
 	FoW.clear();*/
 
+	const Rect &minimap_pos = adventureInt->minimap.pos;
 	int3 mapSizes = LOCPLINT->cb->getMapSize();
-	int mw = map[0]->w, mh = map[0]->h;//,
+	int mw = map_[0]->w, mh = map_[0]->h;//,
 		//wo = mw/mapSizes.x, ho = mh/mapSizes.y; //TODO use me
 	for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
 	{
 		if(level>=0 && d!=level)
 			continue;
-		SDL_Surface * pt = CSDL_Ext::newSurface(pos.w, pos.h, CSDL_Ext::std32bppSurface);
+		SDL_Surface * pt = CSDL_Ext::newSurface(minimap_pos.w, minimap_pos.h, CSDL_Ext::std32bppSurface);
 		for (int i=0; i<mw; i++)
 		{
 			for (int j=0; j<mh; j++)
@@ -245,11 +245,11 @@ void CMinimap::initFoW(int level)
 				}
 			}
 		}
-		FoW.push_back(pt);
+		FoW_.push_back(pt);
 	}
 }
 
-void CMinimap::initFlaggableObjs(int level)
+void CMinimapSurfacesRef::initFlaggableObjs(int level)
 {
 	/*for(int g=0; g<flObjs.size(); ++g)
 	{
@@ -257,13 +257,14 @@ void CMinimap::initFlaggableObjs(int level)
 	}
 	flObjs.clear();*/
 
+	const Rect &minimap_pos = adventureInt->minimap.pos;
 	int3 mapSizes = LOCPLINT->cb->getMapSize();
-	int mw = map[0]->w, mh = map[0]->h;
+	int mw = map_[0]->w, mh = map_[0]->h;
 	for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
 	{
 		if(level>=0 && d!=level)
 			continue;
-		SDL_Surface * pt = CSDL_Ext::newSurface(pos.w, pos.h, CSDL_Ext::std32bppSurface);
+		SDL_Surface * pt = CSDL_Ext::newSurface(minimap_pos.w, minimap_pos.h, CSDL_Ext::std32bppSurface);
 		for (int i=0; i<mw; i++)
 		{
 			for (int j=0; j<mh; j++)
@@ -271,7 +272,7 @@ void CMinimap::initFlaggableObjs(int level)
 				CSDL_Ext::SDL_PutPixelWithoutRefresh(pt,i,j,0,0,0,0);
 			}
 		}
-		flObjs.push_back(pt);
+		flObjs_.push_back(pt);
 	}
 }
 
@@ -287,7 +288,7 @@ void CMinimap::clickLeft(tribool down, bool previousState)
 {
 	if (down && !(used & MOVE))
 		changeUsedEvents(MOVE, true);
-	else if (!down  &&  used & MOVE)
+	else if (!down	&&	used & MOVE)
 		changeUsedEvents(MOVE, false);
 
 	//ClickableL::clickLeft(down);
@@ -330,8 +331,46 @@ void CMinimap::deactivate()
 	CIntObject::deactivate();
 }
 
+std::vector<SDL_Surface*> & CMinimapSurfacesRef::map()
+{
+	if (!ready) redraw();
+	return map_;
+}
+std::vector<SDL_Surface*> & CMinimapSurfacesRef::FoW()
+{
+	if (!ready) redraw();
+	return FoW_;
+}
+std::vector<SDL_Surface*> & CMinimapSurfacesRef::flObjs()
+{
+	if (!ready) redraw();
+	return flObjs_;
+}
+
+void CMinimapSurfacesRef::free()
+{
+	if (ready)
+	{
+		for (int g = 0; g < map_.size(); ++g)
+			SDL_FreeSurface(map_[g]);
+		map_.clear();
+	
+		for (int g = 0; g < FoW_.size(); ++g)
+			SDL_FreeSurface(FoW_[g]);
+		FoW_.clear();
+	
+		for (int g = 0; g < flObjs_.size(); ++g)
+			SDL_FreeSurface(flObjs_[g]);
+		flObjs_.clear();
+	}
+}
+
 void CMinimap::showTile(const int3 &pos)
 {
+	const int player = adventureInt->player;
+	std::vector<SDL_Surface*> &map = surfs[player].map();
+	std::vector<SDL_Surface*> &FoW = surfs[player].FoW();
+	std::vector<SDL_Surface*> &flObjs = surfs[player].flObjs();
 	int3 mapSizes = LOCPLINT->cb->getMapSize();
 	//drawing terrain
 	int mw = map[0]->w, mh = map[0]->h;
@@ -347,8 +386,8 @@ void CMinimap::showTile(const int3 &pos)
 			if(tile)
 			{
 				if (tile->blocked && (!tile->visitable))
-					SDL_PutPixelWithoutRefresh(map[pos.z], pos.x*wo+ii, pos.y*ho+jj, colorsBlocked[tile->tertype].r, colorsBlocked[tile->tertype].g, colorsBlocked[tile->tertype].b);
-				else SDL_PutPixelWithoutRefresh(map[pos.z], pos.x*wo+ii, pos.y*ho+jj, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
+					SDL_PutPixelWithoutRefresh(surfs[player].map()[pos.z], pos.x*wo+ii, pos.y*ho+jj, colorsBlocked[tile->tertype].r, colorsBlocked[tile->tertype].g, colorsBlocked[tile->tertype].b);
+				else SDL_PutPixelWithoutRefresh(surfs[player].map()[pos.z], pos.x*wo+ii, pos.y*ho+jj, colors[tile->tertype].r, colors[tile->tertype].g, colors[tile->tertype].b);
 			}
 		}
 	}
@@ -403,7 +442,7 @@ void CMinimap::showTile(const int3 &pos)
 	//flaggable objects drawn
 }
 
-void CMinimap::showVisibleTiles(int level)
+void CMinimapSurfacesRef::showVisibleTiles(int level)
 {
 	int3 mapSizes = LOCPLINT->cb->getMapSize();
 	for(int d=0; d<CGI->mh->map->twoLevel+1; ++d)
@@ -416,7 +455,7 @@ void CMinimap::showVisibleTiles(int level)
 			{
 				if(LOCPLINT->cb->isVisible(int3(x, y, d)))
 				{
-					showTile(int3(x, y, d));
+					adventureInt->minimap.showTile(int3(x, y, d));
 				}
 			}
 		}
@@ -425,6 +464,9 @@ void CMinimap::showVisibleTiles(int level)
 
 void CMinimap::hideTile(const int3 &pos)
 {
+	const int player = adventureInt->player;
+	std::vector<SDL_Surface*> &map = surfs[player].map();
+	std::vector<SDL_Surface*> &FoW = surfs[player].FoW();
 	int3 mapSizes = LOCPLINT->cb->getMapSize();
 	//drawing terrain
 	int mw = map[0]->w, mh = map[0]->h;

+ 22 - 9
client/CAdvmapInterface.h

@@ -39,7 +39,25 @@ public:
 	~CAdventureOptions();
 	static void showScenarioInfo();
 };
-	 
+
+class CMinimapSurfacesRef {
+public:
+    CMinimapSurfacesRef();
+    std::vector< SDL_Surface* > &map();
+    std::vector< SDL_Surface* > &FoW();
+    std::vector< SDL_Surface* > &flObjs();
+    void free();
+private:
+	void redraw(int level=-1);// (level==-1) => redraw all levels
+	void initMap(int level=-1);// (level==-1) => redraw all levels
+	void initFoW(int level=-1);// (level==-1) => redraw all levels
+	void initFlaggableObjs(int level=-1);// (level==-1) => redraw all levels
+	void showVisibleTiles(int level=-1);// (level==-1) => redraw all levels
+private:    
+    std::vector< SDL_Surface* > map_, FoW_, flObjs_; //one bitmap for each level (terrain, Fog of War, flaggable objects) (one for underworld, one for surface)
+    bool ready;
+};
+
 /// Minimap which is displayed at the right upper corner of adventure map
 class CMinimap : public CIntObject
 {
@@ -48,17 +66,13 @@ public:
 	SDL_Surface * temps;
 	std::map<int,SDL_Color> colors;
 	std::map<int,SDL_Color> colorsBlocked;
-	std::vector<SDL_Surface *> map, FoW, flObjs; //one bitmap for each level (terrain, Fog of War, flaggable objects)
+
+    std::map<int, CMinimapSurfacesRef> surfs;
 	std::string statusbarTxt, rcText;
 
-	CMinimap(bool draw=true);
+	CMinimap();
 	~CMinimap();
 	void draw(SDL_Surface * to);
-	void redraw(int level=-1);// (level==-1) => redraw all levels
-	void initMap(int level=-1);// (level==-1) => redraw all levels
-	void initFoW(int level=-1);// (level==-1) => redraw all levels
-	void initFlaggableObjs(int level=-1);// (level==-1) => redraw all levels
-
 	void updateRadar();
 
 	void clickRight(tribool down, bool previousState);
@@ -69,7 +83,6 @@ public:
 	void deactivate(); // makes button inactive (but don't deletes)
 	void hideTile(const int3 &pos); //puts FoW
 	void showTile(const int3 &pos); //removes FoW
-	void showVisibleTiles(int level=-1);// (level==-1) => redraw all levels
 };
 
 /// Holds information about which tiles of the terrain are shown/not shown at the screen

+ 18 - 17
client/CBattleInterface.cpp

@@ -40,6 +40,8 @@ const double M_PI = 3.14159265358979323846;
 #endif
 #include <boost/format.hpp>
 
+const time_t CBattleInterface::HOVER_ANIM_DELTA = 1;
+
 /*
  * CBattleInterface.cpp, part of VCMI engine
  *
@@ -1182,10 +1184,11 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
 
 CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen)
 	: queue(NULL), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0), 
-	  activeStack(NULL), stackToActivate(NULL), mouseHoveredStack(-1), previouslyHoveredHex(-1),
+	  activeStack(NULL), stackToActivate(NULL), mouseHoveredStack(-1), lastMouseHoveredStackAnimationTime(-1), previouslyHoveredHex(-1),
 	  currentlyHoveredHex(-1), tacticianInterface(NULL),  spellDestSelectMode(false), spellToCast(NULL),
 	  siegeH(NULL), attackerInt(att), defenderInt(defen), curInt(att), animIDhelper(0), givenCommand(NULL),
 	  myTurn(false), resWindow(NULL), moveStarted(false), moveSh(-1), bresult(NULL)
+      
 {
 	ObjectConstruction h__l__p(this);
 
@@ -1453,7 +1456,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 
 	int channel = CCS->soundh->playSoundFromSet(CCS->soundh->battleIntroSounds);
 	CCS->soundh->setCallback(channel, boost::bind(&CMusicHandler::playMusicFromSet, CCS->musich, CCS->musich->battleMusics, -1));
-	
+    memset(stackCountOutsideHexes, 1, BFIELD_SIZE * sizeof(bool)); //initialize array with trues	
 }
 
 CBattleInterface::~CBattleInterface()
@@ -1990,6 +1993,7 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 {
 	if(activeStack!= NULL && !spellDestSelectMode)
 	{
+        int lastMouseHoveredStack = mouseHoveredStack;
 		mouseHoveredStack = -1;
 		int myNumber = -1; //number of hovered tile
 		for(int g = 0; g < BFIELD_SIZE; ++g)
@@ -2033,12 +2037,16 @@ void CBattleInterface::mouseMoved(const SDL_MouseMotionEvent &sEvent)
 						sprintf(buf, CGI->generaltexth->allTexts[297].c_str(), shere->count == 1 ? shere->getCreature()->nameSing.c_str() : shere->getCreature()->namePl.c_str());
 						console->alterTxt = buf;
 						console->whoSetAlter = 0;
-						mouseHoveredStack = shere->ID;
-						if(creAnims[shere->ID]->getType() == CCreatureAnim::HOLDING && creAnims[shere->ID]->framesInGroup(CCreatureAnim::MOUSEON) > 0)
+                        const time_t curTime = time(NULL);
+						if(shere->ID != lastMouseHoveredStack &&
+                           curTime > lastMouseHoveredStackAnimationTime + HOVER_ANIM_DELTA &&
+                           creAnims[shere->ID]->getType() == CCreatureAnim::HOLDING &&
+                           creAnims[shere->ID]->framesInGroup(CCreatureAnim::MOUSEON) > 0)
 						{
 							creAnims[shere->ID]->playOnce(CCreatureAnim::MOUSEON);
+                            lastMouseHoveredStackAnimationTime = curTime;
 						}
-						
+						mouseHoveredStack = shere->ID;
 					}
 					else if(curInt->cb->battleCanShoot(activeStack,myNumber)) //we can shoot enemy
 					{
@@ -3527,11 +3535,11 @@ void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
 	{
         const THex nextPos = stack->position + (stack->attackerOwned ? 1 : -1);
         const bool edge = stack->position % BFIELD_WIDTH == (stack->attackerOwned ? BFIELD_WIDTH - 2 : 1);
-        const bool moveInside = !edge && !isHexAccessible(nextPos);
+        const bool moveInside = !edge && !stackCountOutsideHexes[nextPos];
 		int xAdd = (stack->attackerOwned ? 220 : 202) +
                    (stack->doubleWide() ? 44 : 0) * (stack->attackerOwned ? +1 : -1) +
                    (moveInside ? amountNormal->w + 10 : 0) * (stack->attackerOwned ? -1 : +1);
-        
+        int yAdd = 260 + ((stack->attackerOwned || moveInside) ? 0 : -15);
 		//blitting amount background box
 		SDL_Surface *amountBG = NULL;
 		boost::shared_ptr<BonusList> spellEffects = stack->getSpellBonuses();
@@ -3560,13 +3568,13 @@ void CBattleInterface::showAliveStack(const CStack *stack, SDL_Surface * to)
 				amountBG = amountEffNeutral;
 			}
 		}
-		SDL_Rect temp_rect = genRect(amountNormal->h, amountNormal->w, creAnims[ID]->pos.x + xAdd, creAnims[ID]->pos.y + 260);
+		SDL_Rect temp_rect = genRect(amountNormal->h, amountNormal->w, creAnims[ID]->pos.x + xAdd, creAnims[ID]->pos.y + yAdd);
 		SDL_BlitSurface(amountBG, NULL, to, &temp_rect);
 		//blitting amount
 		CSDL_Ext::printAtMiddle(
 			makeNumberShort(stack->count),
 			creAnims[ID]->pos.x + xAdd + 15,
-			creAnims[ID]->pos.y + 260 + 5,
+			creAnims[ID]->pos.y + yAdd + 5,
 			FONT_TINY,
 			zwykly,
 			to
@@ -3654,7 +3662,7 @@ void CBattleInterface::redrawBackgroundWithHexes(const CStack * activeStack)
 	attackableHexes.clear();
 	if (activeStack)
 		occupyableHexes = curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes);
-
+    curInt->cb->battleGetStackCountOutsideHexes(stackCountOutsideHexes);
 	//preparating background graphic with hexes and shaded hexes
 	blitAt(background, 0, 0, backgroundWithHexes);
 	if(curInt->sysOpts.printCellBorders)
@@ -3976,13 +3984,6 @@ void CBattleInterface::bTacticNextStack()
 		stackActivated(stacksOfMine.front());
 }
 
-bool CBattleInterface::isHexAccessible(THex nextPos)
-{
-	//!vstd::contains(curInt->cb->battleGetAvailableHexes(stack, true), nextPos)
-	//TODO has to be fast
-	return true;
-}
-
 void CBattleHero::show(SDL_Surface *to)
 {
 	//animation of flag

+ 3 - 1
client/CBattleInterface.h

@@ -435,8 +435,11 @@ private:
 	const CStack * stackToActivate; //when animation is playing, we should wait till the end to make the next stack active; NULL of none
 	void activateStack(); //sets activeStack to stackToActivate etc.
 	int mouseHoveredStack; //stack hovered by mouse; if -1 -> none
+    time_t lastMouseHoveredStackAnimationTime; // time when last mouse hovered animation occured
+    static const time_t HOVER_ANIM_DELTA;
 	std::vector<THex> occupyableHexes, //hexes available for active stack
 		attackableHexes; //hexes attackable by active stack
+    bool stackCountOutsideHexes[BFIELD_SIZE]; // hexes that when in front of a unit cause it's amount box to move back
 	int previouslyHoveredHex; //number of hex that was hovered by the cursor a while ago
 	int currentlyHoveredHex; //number of hex that is supposed to be hovered (for a while it may be inappropriately set, but will be renewed soon)
 	float getAnimSpeedMultiplier() const; //returns multiplier for number of frames in a group
@@ -462,7 +465,6 @@ private:
 	void giveCommand(ui8 action, THex tile, ui32 stack, si32 additional=-1);
 	bool isTileAttackable(const THex & number) const; //returns true if tile 'number' is neighboring any tile from active stack's range or is one of these tiles
 	bool blockedByObstacle(THex hex) const;
-	bool isHexAccessible(THex nextPos);
 	bool isCatapultAttackable(THex hex) const; //returns true if given tile can be attacked by catapult
 
 	std::list<SBattleEffect> battleEffects; //different animations to display on the screen like spell effects

+ 2 - 2
client/Graphics.cpp

@@ -702,12 +702,12 @@ void Graphics::loadFonts()
 
 CDefEssential * Graphics::getDef( const CGObjectInstance * obj )
 {
-	return advmapobjGraphics[obj->defInfo->id][obj->defInfo->subid];
+	return advmapobjGraphics[obj->defInfo->id][obj->defInfo->subid][obj->defInfo->name];
 }
 
 CDefEssential * Graphics::getDef( const CGDefInfo * info )
 {
-	return advmapobjGraphics[info->id][info->subid];
+	return advmapobjGraphics[info->id][info->subid][info->name];
 }
 
 void Graphics::loadErmuToPicture()

+ 1 - 1
client/Graphics.h

@@ -68,7 +68,7 @@ public:
 	CDefHandler * FoWfullHide; //for Fog of War
 	CDefHandler * FoWpartialHide; //for For of War
 
-	std::map<int, std::map<int, CDefEssential *> > advmapobjGraphics;
+	std::map<int, std::map<int, std::map<std::string, CDefEssential *> > > advmapobjGraphics;
 	CDefEssential * getDef(const CGObjectInstance * obj);
 	CDefEssential * getDef(const CGDefInfo * info);
 	//creatures

+ 23 - 36
client/mapHandler.cpp

@@ -249,12 +249,11 @@ void CMapHandler::initObjectRects()
 			|| (obj->ID==HEROI_TYPE && static_cast<const CGHeroInstance*>(obj)->inTownGarrison) //garrisoned hero
 			|| (obj->ID==8 && static_cast<const CGBoat*>(obj)->hero) //boat wih hero (hero graphics is used)
 			|| !obj->defInfo
-			|| !obj->defInfo->handler) //no graphic...
+			|| !graphics->getDef(obj)) //no graphic...
 		{
 			continue;
 		}
-
-		const SDL_Surface *bitmap = obj->defInfo->handler->ourImages[0].bitmap;
+		const SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap;
 		for(int fx=0; fx<bitmap->w>>5; ++fx) //bitmap->w/32
 		{
 			for(int fy=0; fy<bitmap->h>>5; ++fy) //bitmap->h/32
@@ -298,64 +297,49 @@ static void processDef (const CGDefInfo* def)
 {
 	if(def->id == EVENTI_TYPE)
 	{
+        graphics->advmapobjGraphics[def->id][def->subid][def->name] = NULL;
 		return;
 	}
-
-	if(!def->handler) //if object has already set handler (eg. heroes) it should not be overwritten 
+    CDefEssential * ourDef = graphics->getDef(def);
+	if(!ourDef) //if object has already set handler (eg. heroes) it should not be overwritten 
 	{
 		if(def->name.size())
 		{
 			if(vstd::contains(graphics->mapObjectDefs, def->name))
 			{
-				const_cast<CGDefInfo*>(def)->handler = graphics->mapObjectDefs[def->name];
+                graphics->advmapobjGraphics[def->id][def->subid][def->name] = graphics->mapObjectDefs[def->name];
 			}
 			else
 			{
-				graphics->mapObjectDefs[def->name] = const_cast<CGDefInfo*>(def)->handler = CDefHandler::giveDefEss(def->name);
+                graphics->mapObjectDefs[def->name] = graphics->advmapobjGraphics[def->id][def->subid][def->name] = CDefHandler::giveDefEss(def->name);
 			}
 		}
 		else
 		{
 			tlog2 << "No def name for " << def->id << "  " << def->subid << std::endl;
-			const_cast<CGDefInfo*>(def)->handler = NULL;
 			return;
 		}
-
- 		const_cast<CGDefInfo*>(def)->width = def->handler->ourImages[0].bitmap->w/32;
- 		const_cast<CGDefInfo*>(def)->height = def->handler->ourImages[0].bitmap->h/32;
+        ourDef = graphics->getDef(def);
+        
 	}
-	
-	CGDefInfo* pom = const_cast<CGameInfo*>(CGI)->dobjinfo->gobjs[def->id][def->subid]; 
-	if(pom && def->id!=TOWNI_TYPE) 
-	{ 
-		pom->handler = def->handler; 
-		pom->width = pom->handler->ourImages[0].bitmap->w/32; 
-		pom->height = pom->handler->ourImages[0].bitmap->h/32; 
-	} 
-	else if(def->id != HEROI_TYPE && def->id != TOWNI_TYPE) 
-		tlog3 << "\t\tMinor warning: lacking def info for " << def->id << " " << def->subid <<" " << def->name << std::endl; 
-	
 	//alpha transformation
-	for(size_t yy=0; yy < def->handler->ourImages.size(); ++yy)
+	for(size_t yy=0; yy < ourDef->ourImages.size(); ++yy)
 	{
-		CSDL_Ext::alphaTransform(def->handler->ourImages[yy].bitmap);
+		CSDL_Ext::alphaTransform(ourDef->ourImages[yy].bitmap);
 	}
 }
 void CMapHandler::initHeroDef(const CGHeroInstance * h)
 {
-	h->defInfo->handler = graphics->flags1[0]; 
-	h->defInfo->width = h->defInfo->handler->ourImages[0].bitmap->w/32; 
-	h->defInfo->height = h->defInfo->handler->ourImages[0].bitmap->h/32;
+    graphics->advmapobjGraphics[h->defInfo->id][h->defInfo->subid][h->defInfo->name] = graphics->flags1[0];
 }
 void CMapHandler::init()
 {
 	timeHandler th;
 	th.getDif();
 
-	const_cast<CGameInfo*>(CGI)->dobjinfo->gobjs[8][0]->handler = graphics->boatAnims[0]; 
-	const_cast<CGameInfo*>(CGI)->dobjinfo->gobjs[8][1]->handler = graphics->boatAnims[1]; 
-	const_cast<CGameInfo*>(CGI)->dobjinfo->gobjs[8][2]->handler = graphics->boatAnims[2];
-
+    graphics->advmapobjGraphics[8][0]["AB01_.DEF"] = graphics->boatAnims[0];
+    graphics->advmapobjGraphics[8][1]["AB02_.DEF"] = graphics->boatAnims[1];
+    graphics->advmapobjGraphics[8][2]["AB03_.DEF"] = graphics->boatAnims[2];
 	// Size of visible terrain.
 	int mapW = conf.go()->ac.advmapW;
 	int mapH = conf.go()->ac.advmapH;
@@ -387,7 +371,7 @@ void CMapHandler::init()
 
 	for(int i=0;i<map->heroes.size();i++)
 	{
-		if( !map->heroes[i]->defInfo->handler )
+		if( !graphics->getDef(map->heroes[i]) )
 		{
 			initHeroDef(map->heroes[i]);
 		}
@@ -527,6 +511,9 @@ void CMapHandler::terrainRect( int3 top_tile, unsigned char anim, const std::vec
 			for(int h=0; h < objects.size(); ++h)
 			{
 				const CGObjectInstance *obj = objects[h].first;
+                if (!graphics->getDef(obj))
+                    processDef(obj->defInfo);
+
 				ui8 color = obj->tempOwner;
 
 				//checking if object has non-empty graphic on this tile
@@ -639,7 +626,7 @@ void CMapHandler::terrainRect( int3 top_tile, unsigned char anim, const std::vec
 				}
 				else //blit normal object
 				{
-					const std::vector<Cimage> &ourImages = obj->defInfo->handler->ourImages;
+					const std::vector<Cimage> &ourImages = graphics->getDef(obj)->ourImages;
 					SDL_Surface *bitmap = ourImages[(anim+obj->animPhaseShift)%ourImages.size()].bitmap;
 
 					//setting appropriate flag color
@@ -835,10 +822,10 @@ std::pair<SDL_Surface *, bool> CMapHandler::getVisBitmap( const int3 & pos, cons
 
 bool CMapHandler::printObject(const CGObjectInstance *obj)
 {
-	if(!obj->defInfo->handler)
+    if (!graphics->getDef(obj))
 		processDef(obj->defInfo);
 
-	const SDL_Surface *bitmap = obj->defInfo->handler->ourImages[0].bitmap;
+	const SDL_Surface *bitmap = graphics->getDef(obj)->ourImages[0].bitmap; 
 	const int tilesW = bitmap->w/32;
 	const int tilesH = bitmap->h/32;
 
@@ -879,7 +866,7 @@ bool CMapHandler::printObject(const CGObjectInstance *obj)
 
 bool CMapHandler::hideObject(const CGObjectInstance *obj)
 {
-	CDefEssential * curd = obj->defInfo->handler;
+	CDefEssential * curd = graphics->getDef(obj);
 	if(!curd) return false;
 	const SDL_Surface *bitmap = curd->ourImages[0].bitmap;
 	for(int fx=0; fx<bitmap->w/32; ++fx)

+ 0 - 2
lib/CDefObjInfoHandler.cpp

@@ -30,7 +30,6 @@ bool CGDefInfo::isVisitable() const
 }
 CGDefInfo::CGDefInfo()
 {
-	handler = NULL;
 	visitDir = (8|16|32|64|128); //4,5,6,7,8 - any not-from-up direction
 
 	width = height = -1;
@@ -59,7 +58,6 @@ void CDefObjInfoHandler::load()
 	for(int hh=0; hh<objNumber; ++hh)
 	{
 		CGDefInfo* nobj = new CGDefInfo();
-		nobj->handler = NULL;
 		std::string dump;
 		inp>>nobj->name;
 		

+ 0 - 1
lib/CDefObjInfoHandler.h

@@ -29,7 +29,6 @@ public:
 	si32 id, subid; //of object described by this defInfo
 	si32 terrainAllowed, //on which terrain it is possible to place object
 		 terrainMenu; //in which menus in map editor object will be showed
-	CDefEssential * handler; 
 	si32 width, height; //tiles
 	si32 type; //(0- ground, 1- towns, 2-creatures, 3- heroes, 4-artifacts, 5- resources)   
 	si32 printPriority;

+ 13 - 16
lib/CGameState.cpp

@@ -1737,28 +1737,25 @@ int CGameState::getPlayerRelations( ui8 color1, ui8 color2 )
 
 void CGameState::loadTownDInfos()
 {
-	for(int i=0;i<F_NUMBER;i++)
-	{
+    int i;
+	const JsonNode config(DATA_DIR "/config/towns_defs.json");
+    JsonVector vec = config["town_defnames"].Vector();
+    assert(vec.size() == F_NUMBER);
+    for (i = 0; i < vec.size(); ++i) {
 		villages[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
 		forts[i] = VLC->dobjinfo->castles[i];
 		map->defy.push_back(forts[i]);
 		capitols[i] = new CGDefInfo(*VLC->dobjinfo->castles[i]);
 	}
 
-	std::ifstream ifs(DATA_DIR "/config/townsDefs.txt");
-	int ccc;
-	ifs>>ccc;
-	for(int i=0; i < ccc*2; i++)
-	{
-		CGDefInfo *n;
-		if(i<ccc)
-			n = villages[i];
-		else 
-			n = capitols[i%ccc];
-
-		ifs >> n->name;
-		map->defy.push_back(n);
-	}
+    i = 0;
+    BOOST_FOREACH(const JsonNode &t, vec) {
+        villages[i]->name = t["village"].String();
+        capitols[i]->name = t["capitol"].String();
+        ++i;
+    }
+    for (i = 0; i < vec.size(); ++i) map->defy.push_back(villages[i]);
+    for (i = 0; i < vec.size(); ++i) map->defy.push_back(capitols[i]);
 }
 
 void CGameState::getNeighbours(const TerrainTile &srct, int3 tile, std::vector<int3> &vec, const boost::logic::tribool &onLand, bool limitCoastSailing)

+ 13 - 0
lib/IGameCallback.cpp

@@ -220,6 +220,19 @@ void CBattleInfoCallback::getStackQueue( std::vector<const CStack *> &out, int h
 	gs->curB->getStackQueue(out, howMany);
 }
 
+void CBattleInfoCallback::battleGetStackCountOutsideHexes(bool *ac)
+{
+	if(!gs->curB)
+	{
+		tlog2<<"battleGetAvailableHexes called when there is no battle!"<<std::endl;
+        for (int i = 0; i < BFIELD_SIZE; ++i) ac[i] = false;
+	}
+    else {
+        std::set<THex> ignored;
+        gs->curB->getAccessibilityMap(ac, false /*ignored*/, false, false, ignored, false /*ignored*/, NULL);
+    }
+}
+
 std::vector<THex> CBattleInfoCallback::battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<THex> * attackable)
 {
 	//boost::shared_lock<boost::shared_mutex> lock(*gs->mx);

+ 1 - 0
lib/IGameCallback.h

@@ -97,6 +97,7 @@ public:
 	THex battleGetPos(int stack); //returns position (tile ID) of stack
 	TStacks battleGetStacks(EStackOwnership whose = MINE_AND_ENEMY, bool onlyAlive = true); //returns stacks on battlefield
 	void getStackQueue( std::vector<const CStack *> &out, int howMany ); //returns vector of stack in order of their move sequence
+    void battleGetStackCountOutsideHexes(bool *ac); // returns hexes which when in front of a stack cause us to move the amount box back
 	std::vector<THex> battleGetAvailableHexes(const CStack * stack, bool addOccupiable, std::vector<THex> * attackable = NULL); //returns numbers of hexes reachable by creature with id ID
 	std::vector<int> battleGetDistances(const CStack * stack, THex hex = THex::INVALID, THex * predecessors = NULL); //returns vector of distances to [dest hex number]
 	bool battleCanShoot(const CStack * stack, THex dest); //returns true if unit with id ID can shoot to dest