Parcourir la source

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

ori.bar il y a 14 ans
Parent
commit
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