瀏覽代碼

Replace SDL_Point and SDL_Rect with Gfx::Point and Gfx::Rect,
synchronization with trunk.

paracelsus 12 年之前
父節點
當前提交
06e2e6ac10
共有 58 個文件被更改,包括 1958 次插入808 次删除
  1. 9 6
      client/AdventureMapClasses.cpp
  2. 62 59
      client/BattleInterface/CBattleInterface.cpp
  3. 3 3
      client/BattleInterface/CBattleInterface.h
  4. 15 18
      client/BattleInterface/CBattleInterfaceClasses.cpp
  5. 2 2
      client/BattleInterface/CBattleInterfaceClasses.h
  6. 22 23
      client/CAdvmapInterface.cpp
  7. 4 4
      client/CAnimation.cpp
  8. 2 2
      client/CBitmapHandler.cpp
  9. 0 1
      client/CCastleInterface.cpp
  10. 6 7
      client/CCreatureWindow.cpp
  11. 1 1
      client/CHeroWindow.cpp
  12. 2 0
      client/CKingdomInterface.cpp
  13. 28 11
      client/CMT.cpp
  14. 9 9
      client/CMessage.cpp
  15. 5 5
      client/CPlayerInterface.cpp
  16. 23 29
      client/CPreGame.cpp
  17. 5 5
      client/CSpellWindow.cpp
  18. 3 3
      client/CSpellWindow.h
  19. 2 2
      client/FunctionList.h
  20. 23 20
      client/GUIClasses.cpp
  21. 3 3
      client/GUIClasses.h
  22. 43 0
      client/Gfx/Basic.cpp
  23. 60 7
      client/Gfx/Basic.h
  24. 2 2
      client/Gfx/Images.cpp
  25. 0 2
      client/Graphics.h
  26. 3 3
      client/UIFramework/CGuiHandler.cpp
  27. 3 2
      client/UIFramework/CGuiHandler.h
  28. 14 18
      client/UIFramework/CIntObject.cpp
  29. 13 11
      client/UIFramework/CIntObject.h
  30. 51 54
      client/UIFramework/CIntObjectClasses.cpp
  31. 5 10
      client/UIFramework/CIntObjectClasses.h
  32. 21 21
      client/UIFramework/Fonts.cpp
  33. 11 10
      client/UIFramework/Fonts.h
  34. 4 1
      client/UIFramework/Geometries.cpp
  35. 5 1
      client/UIFramework/Geometries.h
  36. 6 6
      client/UIFramework/SDL_Extensions.cpp
  37. 8 11
      client/UIFramework/SDL_Extensions.h
  38. 1 0
      client/VCMI_client.vcxproj
  39. 9 2
      client/VCMI_client.vcxproj.filters
  40. 40 39
      client/mapHandler.cpp
  41. 3 3
      client/mapHandler.h
  42. 88 8
      config/artifacts.json
  43. 526 0
      config/bonuses.json
  44. 387 0
      config/bonuses_texts.json
  45. 0 66
      config/bonusnames.json
  46. 0 81
      config/commanders.json
  47. 6 0
      config/gameConfig.json
  48. 180 36
      config/heroClasses.json
  49. 148 129
      lib/CArtHandler.cpp
  50. 15 10
      lib/CArtHandler.h
  51. 21 6
      lib/CBattleCallback.cpp
  52. 6 6
      lib/CBonusTypeHandler.cpp
  53. 1 1
      lib/CCreatureHandler.cpp
  54. 13 13
      lib/CGameState.cpp
  55. 32 27
      lib/CHeroHandler.cpp
  56. 2 2
      lib/CHeroHandler.h
  57. 2 2
      lib/CObjectHandler.cpp
  58. 0 5
      lib/StringConstants.h

+ 9 - 6
client/AdventureMapClasses.cpp

@@ -154,10 +154,11 @@ void CList::selectIndex(int which)
 void CList::selectNext()
 {
 	int index = getSelectedIndex();
+
 	if (index < 0)
 		selectIndex(0);
-	else if (index + 1 < list->size())
-		selectIndex(index+1);
+	else if ((size_t)++index < list->size())
+		selectIndex(index);
 }
 
 void CList::selectPrev()
@@ -177,7 +178,7 @@ CHeroList::CEmptyHeroItem::CEmptyHeroItem()
 	auto mana = new CAnimImage("IMANA", 0, 0, move->pos.w + img->pos.w + 2, 1 );
 
 	pos.w = mana->pos.w + mana->pos.x - pos.x;
-	pos.h = std::max(std::max<ui16>(move->pos.h + 1, mana->pos.h + 1), img->pos.h);
+	pos.h = std::max(std::max<ui32>(move->pos.h + 1, mana->pos.h + 1), img->pos.h);
 }
 
 CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero):
@@ -190,7 +191,7 @@ CHeroList::CHeroItem::CHeroItem(CHeroList *parent, const CGHeroInstance * Hero):
 	mana     = new CAnimImage("IMANA", 0, 0, movement->pos.w + portrait->pos.w + 2, 1 );
 
 	pos.w = mana->pos.w + mana->pos.x - pos.x;
-	pos.h = std::max(std::max<ui16>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
+	pos.h = std::max(std::max<ui32>(movement->pos.h + 1, mana->pos.h + 1), portrait->pos.h);
 
 	update();
 }
@@ -220,7 +221,8 @@ void CHeroList::CHeroItem::open()
 
 void CHeroList::CHeroItem::showTooltip()
 {
-	CRClickPopup::createAndPush(hero, GH.current->motion);
+	auto &motion = GH.current->motion;
+	CRClickPopup::createAndPush(hero, Point(motion.x, motion.y));
 }
 
 std::string CHeroList::CHeroItem::getHoverText()
@@ -312,7 +314,8 @@ void CTownList::CTownItem::open()
 
 void CTownList::CTownItem::showTooltip()
 {
-	CRClickPopup::createAndPush(town, GH.current->motion);
+	auto &motion = GH.current->motion;
+	CRClickPopup::createAndPush(town, Point(motion.x, motion.y));
 }
 
 std::string CTownList::CTownItem::getHoverText()

+ 62 - 59
client/BattleInterface/CBattleInterface.cpp

@@ -89,7 +89,7 @@ void CBattleInterface::addNewAnim(CBattleAnimation * anim)
 	animsAreDisplayed.setn(true);
 }
 
-CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen)
+CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen)
 	: queue(NULL), attackingHeroInstance(hero1), defendingHeroInstance(hero2), animCount(0),
 	  activeStack(NULL), stackToActivate(NULL), selectedStack(NULL), mouseHoveredStack(-1), lastMouseHoveredStackAnimationTime(-1), previouslyHoveredHex(-1),
 	  currentlyHoveredHex(-1), attackingHex(-1), tacticianInterface(NULL),  stackCanCastSpell(false), creatureCasting(false), spellDestSelectMode(false), spellSelMode(NO_LOCATION), spellToCast(NULL), sp(NULL),
@@ -158,9 +158,9 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 			SDL_Surface * moat = BitmapHandler::loadBitmap( siegeH->getSiegeName(13) ),
 				* mlip = BitmapHandler::loadBitmap( siegeH->getSiegeName(14) );
 
-			auto & info = siegeH->town->town->clientInfo;
-			Point moatPos(info.siegePositions[13].x, info.siegePositions[13].y);
-			Point mlipPos(info.siegePositions[14].x, info.siegePositions[14].y);
+			auto & siegePositions = siegeH->town->town->clientInfo.siegePositions;
+			Point moatPos(siegePositions[13].x, siegePositions[13].y);
+			Point mlipPos(siegePositions[14].x, siegePositions[14].y);
 
 			if(moat) //eg. tower has no moat
 				blitAt(moat, moatPos.x,moatPos.y, background);
@@ -564,39 +564,37 @@ void CBattleInterface::deactivate()
 	LOCPLINT->cingconsole->deactivate();
 }
 
-void CBattleInterface::showAll(SDL_Surface * to)
+void CBattleInterface::showAll()
 {
-	show(to);
+	show();
 }
 
-void CBattleInterface::show(SDL_Surface * to)
+void CBattleInterface::show()
 {
 	std::vector<const CStack*> stacks = curInt->cb->battleGetAllStacks(); //used in a few places
 	++animCount;
-	if(!to) //"evaluating" to
-		to = screen;
 
-	SDL_Rect buf;
-	SDL_GetClipRect(to, &buf);
-	SDL_SetClipRect(to, &pos);
+//*	SDL_Rect buf;
+//*	SDL_GetClipRect(to, &buf);
+//*	SDL_SetClipRect(to, &pos);
 
 	//printing background and hexes
 	if(activeStack != NULL && creAnims[activeStack->ID]->getType() != CCreatureAnim::MOVING) //show everything with range
 	{
-		blitAt(backgroundWithHexes, pos.x, pos.y, to);
+//*		blitAt(backgroundWithHexes, pos.x, pos.y, to);
 	}
 	else
 	{
 		//showing background
-		blitAt(background, pos.x, pos.y, to);
+//*		blitAt(background, pos.x, pos.y, to);
 		if(settings["battle"]["cellBorders"].Bool())
 		{
-			CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, to, &pos);
+//*			CSDL_Ext::blit8bppAlphaTo24bpp(cellBorders, NULL, to, &pos);
 		}
 		//Blit absolute obstacles
-		BOOST_FOREACH(auto &oi, curInt->cb->battleGetAllObstacles())
-			if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
-				blitAt(imageOfObstacle(*oi), pos.x + oi->getInfo().width, pos.y + oi->getInfo().height, to);
+//*		BOOST_FOREACH(auto &oi, curInt->cb->battleGetAllObstacles())
+//*			if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
+//*				blitAt(imageOfObstacle(*oi), pos.x + oi->getInfo().width, pos.y + oi->getInfo().height, to);
 	}
 	//printing hovered cell
 	for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
@@ -635,8 +633,8 @@ void CBattleInterface::show(SDL_Surface * to)
 					{
 						int x = 14 + ((shadedHex/GameConstants::BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(shadedHex%GameConstants::BFIELD_WIDTH) + pos.x;
 						int y = 86 + 42 * (shadedHex/GameConstants::BFIELD_WIDTH) + pos.y;
-						SDL_Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
-						CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &temp_rect);
+						Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
+//*						CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &temp_rect);
 					}
 				}
 			}
@@ -649,8 +647,8 @@ void CBattleInterface::show(SDL_Surface * to)
 					{
 						int x = 14 + ((hex/GameConstants::BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(hex%GameConstants::BFIELD_WIDTH) + pos.x;
 						int y = 86 + 42 * (hex/GameConstants::BFIELD_WIDTH) + pos.y;
-						SDL_Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
-						CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &temp_rect);
+						Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
+//*						CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &temp_rect);
 					}
 				}
 
@@ -667,8 +665,8 @@ void CBattleInterface::show(SDL_Surface * to)
 						{
 							int x = 14 + ((hex / GameConstants::BFIELD_WIDTH ) % 2 == 0 ? 22 : 0) + 44 * (hex % GameConstants::BFIELD_WIDTH) + pos.x;
 							int y = 86 + 42 * (hex / GameConstants::BFIELD_WIDTH) + pos.y;
-							SDL_Rect temp_rect = genRect (cellShade->h, cellShade->w, x, y);
-							CSDL_Ext::blit8bppAlphaTo24bpp (cellShade, NULL, to, &temp_rect);
+							Rect temp_rect = genRect (cellShade->h, cellShade->w, x, y);
+//*							CSDL_Ext::blit8bppAlphaTo24bpp (cellShade, NULL, to, &temp_rect);
 						}
 					}
 				}
@@ -676,18 +674,18 @@ void CBattleInterface::show(SDL_Surface * to)
 				//always highlight pointed hex
 				int x = 14 + ((b/GameConstants::BFIELD_WIDTH)%2==0 ? 22 : 0) + 44*(b%GameConstants::BFIELD_WIDTH) + pos.x;
 				int y = 86 + 42 * (b/GameConstants::BFIELD_WIDTH) + pos.y;
-				SDL_Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
-				CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &temp_rect);
+				Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
+//*				CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, to, &temp_rect);
 			}
 		}
 	}
 
 
-	SDL_SetClipRect(to, &buf); //restoring previous clip_rect
+//*	SDL_SetClipRect(to, &buf); //restoring previous clip_rect
 
 	//prevents blitting outside this window
-	SDL_GetClipRect(to, &buf);
-	SDL_SetClipRect(to, &pos);
+//*	SDL_GetClipRect(to, &buf);
+//*	SDL_SetClipRect(to, &pos);
 
 	//preparing obstacles to be shown
 	auto obstacles = curInt->cb->battleGetAllObstacles();
@@ -772,8 +770,8 @@ void CBattleInterface::show(SDL_Surface * to)
 		{
 			//we may have changed active interface (another side in hot-seat), 
 			// so we can't continue drawing with old setting. So we call ourselves again and end.
-			SDL_SetClipRect(to, &buf); //restoring previous clip_rect
-			show(to);
+//*			SDL_SetClipRect(to, &buf); //restoring previous clip_rect
+			show();
 			return;
 		}
 	}
@@ -782,7 +780,7 @@ void CBattleInterface::show(SDL_Surface * to)
 	{
 		for(size_t v=0; v<stackDeadByHex[b].size(); ++v)
 		{
-			creAnims[stackDeadByHex[b][v]->ID]->nextFrame(to, creAnims[stackDeadByHex[b][v]->ID]->pos.x, creAnims[stackDeadByHex[b][v]->ID]->pos.y, creDir[stackDeadByHex[b][v]->ID], animCount, false); //increment always when moving, never if stack died
+//*			creAnims[stackDeadByHex[b][v]->ID]->nextFrame(to, creAnims[stackDeadByHex[b][v]->ID]->pos.x, creAnims[stackDeadByHex[b][v]->ID]->pos.y, creDir[stackDeadByHex[b][v]->ID], animCount, false); //increment always when moving, never if stack died
 		}
 	}
 	std::vector<const CStack *> flyingStacks; //flying stacks should be displayed later, over other stacks and obstacles
@@ -790,8 +788,8 @@ void CBattleInterface::show(SDL_Surface * to)
 	{
 		for(int b = 0; b < GameConstants::BFIELD_SIZE; ++b) //showing alive stacks
 		{
-			showObstacles(&hexToObstacle, obstacles, b, to);
-			showAliveStacks(stackAliveByHex, b, &flyingStacks, to);
+//*			showObstacles(&hexToObstacle, obstacles, b, to);
+//*			showAliveStacks(stackAliveByHex, b, &flyingStacks, to);
 		}
 	}
 	// Siege drawing
@@ -859,9 +857,9 @@ void CBattleInterface::show(SDL_Surface * to)
 				for (int k = xMin; k <= xMax; k++)
 				{
 					int hex = j * 17 + k;
-					showObstacles(&hexToObstacle, obstacles, hex, to);
-					showAliveStacks(stackAliveByHex, hex, &flyingStacks, to);
-					showPieceOfWall(to, hex, stacks);
+//*					showObstacles(&hexToObstacle, obstacles, hex, to);
+//*					showAliveStacks(stackAliveByHex, hex, &flyingStacks, to);
+//*					showPieceOfWall(to, hex, stacks);
 				}
 
 				++runNum;
@@ -870,12 +868,12 @@ void CBattleInterface::show(SDL_Surface * to)
 	}
 
 	for(size_t b = 0; b < flyingStacks.size(); ++b) //showing flying stacks
-		showAliveStack(flyingStacks[b], to);
+		showAliveStack(flyingStacks[b], nullptr);
 
 	//units shown
 
 	// Show projectiles
-	projectileShowHelper(to);
+//*	projectileShowHelper(to);
 
 	//showing spell effects
 	if(battleEffects.size())
@@ -883,15 +881,15 @@ void CBattleInterface::show(SDL_Surface * to)
 		for(std::list<BattleEffect>::iterator it = battleEffects.begin(); it!=battleEffects.end(); ++it)
 		{
 			SDL_Surface * bitmapToBlit = it->anim->ourImages[(it->frame)%it->anim->ourImages.size()].bitmap;
-			SDL_Rect temp_rect = genRect(bitmapToBlit->h, bitmapToBlit->w, it->x, it->y);
-			SDL_BlitSurface(bitmapToBlit, NULL, to, &temp_rect);
+			Rect temp_rect = genRect(bitmapToBlit->h, bitmapToBlit->w, it->x, it->y);
+//*			SDL_BlitSurface(bitmapToBlit, NULL, to, &temp_rect);
 		}
 	}
 
-	SDL_SetClipRect(to, &buf); //restoring previous clip_rect
+//*	SDL_SetClipRect(to, &buf); //restoring previous clip_rect
 
 	//showing menu background and console
-	blitAt(menu, pos.x, 556 + pos.y, to);
+//*	blitAt(menu, pos.x, 556 + pos.y, to);
 
 	if(tacticsMode)
 	{
@@ -915,7 +913,7 @@ void CBattleInterface::show(SDL_Surface * to)
 	bDefence->showAll();
 
 	//showing in-game console
-	LOCPLINT->cingconsole->show(to);
+	LOCPLINT->cingconsole->show();
 
 	Rect posWithQueue = Rect(pos.x, pos.y, 800, 600);
 
@@ -930,14 +928,14 @@ void CBattleInterface::show(SDL_Surface * to)
 		//showing queue
 		if(!bresult)
 			queue->showAll();
-		else
-			queue->blitBg(to);
+//*		else
+//*			queue->blitBg(to);
 	}
 
 	//printing border around interface
 	if(screen->w != 800 || screen->h !=600)
 	{
-		CMessage::drawBorder(curInt->playerID,to,posWithQueue.w + 28, posWithQueue.h + 28, posWithQueue.x-14, posWithQueue.y-15);
+//*		CMessage::drawBorder(curInt->playerID,to,posWithQueue.w + 28, posWithQueue.h + 28, posWithQueue.x-14, posWithQueue.y-15);
 	}
 }
 
@@ -1366,8 +1364,9 @@ void CBattleInterface::newStack(const CStack * stack)
 
 		if (posID != 0)
 		{
-			coords.x = siegeH->town->town->clientInfo.siegePositions[posID].x + this->pos.x;
-			coords.y = siegeH->town->town->clientInfo.siegePositions[posID].y + this->pos.y;
+			auto & siegePositions = siegeH->town->town->clientInfo.siegePositions;
+			coords.x = siegePositions[posID].x + this->pos.x;
+			coords.y = siegePositions[posID].y + this->pos.y;
 		}
 	}
 	else
@@ -1595,7 +1594,7 @@ void CBattleInterface::displayBattleFinished()
 {
 	CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
 
-	SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
+	Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
 	resWindow = new CBattleResultWindow(*bresult, temp_rect, this);
 	GH.pushInt(resWindow);
 }
@@ -1630,7 +1629,8 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 		{ //common ice bolt and magic arrow part
 			//initial variables
 			std::string animToDisplay;
-			Point srccoord = (sc->side ? Point(770, 60) : Point(30, 60)) + pos;
+			Point srccoord(pos);
+			srccoord += (sc->side ? Point(770, 60) : Point(30, 60));
 			Point destcoord = CClickableHex::getXYUnitAnim(sc->tile, !sc->side, curInt->cb->battleGetStackByPos(sc->tile), this); //position attacked by arrow
 			destcoord.x += 250; destcoord.y += 240;
 
@@ -1861,8 +1861,10 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
 	//mana absorption
 	if (sc->manaGained)
 	{
-		Point leftHero = Point(15, 30) + pos;
-		Point rightHero = Point(755, 30) + pos;
+		Point leftHero(15, 30);
+		leftHero += pos;
+		Point rightHero(755, 30);
+		rightHero += pos;
 		addNewAnim(new CSpellEffectAnimation(this, sc->side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero.x, leftHero.y, 0, 0, false));
 		addNewAnim(new CSpellEffectAnimation(this, sc->side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero.x, rightHero.y, 0, 0, false));
 	}
@@ -2277,8 +2279,8 @@ 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 + yAdd);
-		SDL_BlitSurface(amountBG, NULL, to, &temp_rect);
+		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
 
 		Point textPos(creAnims[ID]->pos.x + xAdd + 15, creAnims[ID]->pos.y + yAdd + 5);
@@ -2403,8 +2405,8 @@ void CBattleInterface::redrawBackgroundWithHexes(const CStack * activeStack)
 			int j = hex.getX()-1; //column
 			int x = 58 + (i%2==0 ? 22 : 0) + 44*j;
 			int y = 86 + 42 * i;
-			SDL_Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
-			CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, backgroundWithHexes, &temp_rect);
+			Rect temp_rect = genRect(cellShade->h, cellShade->w, x, y);
+//*			CSDL_Ext::blit8bppAlphaTo24bpp(cellShade, NULL, backgroundWithHexes, &temp_rect);
 		}
 	}
 }
@@ -3647,8 +3649,9 @@ void CBattleInterface::SiegeHelper::printPartOfWall(SDL_Surface * to, int what)
 
 	if (what >= 1 && what <= 17)
 	{
-		pos.x = owner->siegeH->town->town->clientInfo.siegePositions[what].x + owner->pos.x;
-		pos.y = owner->siegeH->town->town->clientInfo.siegePositions[what].y + owner->pos.y;
+		auto & siegePositions = owner->siegeH->town->town->clientInfo.siegePositions;
+		pos.x = siegePositions[what].x + owner->pos.x;
+		pos.y = siegePositions[what].y + owner->pos.y;
 	}
 
 	if(pos.x != -1)

+ 3 - 3
client/BattleInterface/CBattleInterface.h

@@ -207,7 +207,7 @@ public:
 	ui32 animIDhelper; //for giving IDs for animations
 	static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
 
-	CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const SDL_Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen); //c-tor
+	CBattleInterface(const CCreatureSet * army1, const CCreatureSet * army2, CGHeroInstance *hero1, CGHeroInstance *hero2, const Rect & myRect, CPlayerInterface * att, CPlayerInterface * defen); //c-tor
 	~CBattleInterface(); //d-tor
 
 	//std::vector<TimeInterested*> timeinterested; //animation handling
@@ -245,8 +245,8 @@ public:
 	//napisz tu klase odpowiadajaca za wyswietlanie bitwy i obsluge uzytkownika, polecenia ma przekazywac callbackiem
 	void activate();
 	void deactivate();
-	void showAll(SDL_Surface * to);
-	void show(SDL_Surface * to);
+	void showAll();
+	void show();
 	void keyPressed(const SDL_KeyboardEvent & key);
 	void mouseMoved(const SDL_MouseMotionEvent &sEvent);
 	void clickRight(tribool down, bool previousState);

+ 15 - 18
client/BattleInterface/CBattleInterfaceClasses.cpp

@@ -114,7 +114,7 @@ CBattleConsole::CBattleConsole() : lastShown(-1), alterTxt(""), whoSetAlter(0)
 void CBattleHero::show(SDL_Surface * to)
 {
 	//animation of flag
-	SDL_Rect temp_rect;
+	Rect temp_rect;
 	if(flip)
 	{
 		temp_rect = genRect(
@@ -132,6 +132,7 @@ void CBattleHero::show(SDL_Surface * to)
 			pos.x + 72,
 			pos.y + 39);
 	}
+/*
 	CSDL_Ext::blit8bppAlphaTo24bpp(
 		flag->ourImages[flagAnim].bitmap,
 		NULL,
@@ -141,6 +142,7 @@ void CBattleHero::show(SDL_Surface * to)
 	//animation of hero
 	SDL_Rect rect = pos;
 	CSDL_Ext::blit8bppAlphaTo24bpp(dh->ourImages[currentFrame].bitmap, NULL, to, &rect);
+*/
 
 	if ( ++animCount == 4 )
 	{
@@ -241,7 +243,7 @@ CBattleHero::~CBattleHero()
 	delete flag;
 }
 
-CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner)
+CBattleOptionsWindow::CBattleOptionsWindow(const Rect & position, CBattleInterface *owner)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	pos = position;
@@ -302,7 +304,7 @@ void CBattleOptionsWindow::bExitf()
 	GH.popIntTotally(this);
 }
 
-CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const SDL_Rect & pos, CBattleInterface * _owner)
+CBattleResultWindow::CBattleResultWindow(const BattleResult &br, const Rect & pos, CBattleInterface * _owner)
 : owner(_owner)
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
@@ -490,19 +492,14 @@ void CBattleResultWindow::bExitf()
 Point CClickableHex::getXYUnitAnim(const int & hexNum, const bool & attacker, const CStack * stack, const CBattleInterface * cbi)
 {
 	Point ret(-500, -500); //returned value
-	if(stack && stack->position < 0) //creatures in turrets
+	if (stack && stack->position < 0) //creatures in turrets
 	{
-		switch(stack->position)
+		auto sp = stack->position;
+		if (sp >= -4 && sp <= -2)
 		{
-		case -2: //keep
-			ret = cbi->siegeH->town->town->clientInfo.siegePositions[18];
-			break;
-		case -3: //lower turret
-			ret = cbi->siegeH->town->town->clientInfo.siegePositions[19];
-			break;
-		case -4: //upper turret
-			ret = cbi->siegeH->town->town->clientInfo.siegePositions[20];
-			break;	
+			// sp: -2 = keep, -3 = lower turret, -4 = upper turret
+			auto & siegePositions = cbi->siegeH->town->town->clientInfo.siegePositions;
+			ret = Point(siegePositions[16-sp].x, siegePositions[16-sp].y);
 		}
 	}
 	else
@@ -531,7 +528,7 @@ Point CClickableHex::getXYUnitAnim(const int & hexNum, const bool & attacker, co
 		}
 	}
 	//returning
-	return ret +CPlayerInterface::battleInt->pos;
+	return ret += CPlayerInterface::battleInt->pos;
 }
 
 void CClickableHex::hover(bool on)
@@ -667,9 +664,9 @@ void CStackQueue::blitBg( SDL_Surface * to )
 {
 	if(bg)
 	{
-		SDL_SetClipRect(to, &pos);
-		CSDL_Ext::fillTexture(to, bg);
-		SDL_SetClipRect(to, nullptr);
+//*		SDL_SetClipRect(to, &pos);
+//*		CSDL_Ext::fillTexture(to, bg);
+//*		SDL_SetClipRect(to, nullptr);
 	}
 }
 

+ 2 - 2
client/BattleInterface/CBattleInterfaceClasses.h

@@ -76,7 +76,7 @@ private:
 
 	std::vector<CLabel*> labels;
 public:
-	CBattleOptionsWindow(const SDL_Rect &position, CBattleInterface *owner); //c-tor
+	CBattleOptionsWindow(const Rect &position, CBattleInterface *owner); //c-tor
 
 	void bDefaultf(); //default button callback
 	void bExitf(); //exit button callback
@@ -89,7 +89,7 @@ private:
 	CAdventureMapButton *exit;
 	CBattleInterface *owner;
 public:
-	CBattleResultWindow(const BattleResult & br, const SDL_Rect & pos, CBattleInterface * _owner); //c-tor
+	CBattleResultWindow(const BattleResult & br, const Rect & pos, CBattleInterface * _owner); //c-tor
 	~CBattleResultWindow(); //d-tor
 
 	void bExitf(); //exit button callback

+ 22 - 23
client/CAdvmapInterface.cpp

@@ -199,25 +199,25 @@ void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
 				if (hvx<0 && hvy<0)
 				{
 					Rect dstRect = genRect(32, 32, x + moveX, y + moveY);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, NULL, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, NULL, to, &dstRect);
 				}
 				else if(hvx<0)
 				{
 					Rect srcRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w, 0, 0);
 					Rect dstRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w, x + moveX, y + moveY);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
 				}
 				else if (hvy<0)
 				{
 					Rect srcRect = genRect(arrows->ourImages[pn].bitmap->h, arrows->ourImages[pn].bitmap->w-hvx, 0, 0);
 					Rect dstRect = genRect(arrows->ourImages[pn].bitmap->h, arrows->ourImages[pn].bitmap->w-hvx, x + moveX, y + moveY);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
 				}
 				else
 				{
 					Rect srcRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w-hvx, 0, 0);
 					Rect dstRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w-hvx, x + moveX, y + moveY);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
 				}
 			}
 			else //standard version
@@ -225,25 +225,25 @@ void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
 				if (hvx<0 && hvy<0)
 				{
 					Rect dstRect = genRect(32, 32, x, y);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, NULL, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, NULL, to, &dstRect);
 				}
 				else if(hvx<0)
 				{
 					Rect srcRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w, 0, 0);
 					Rect dstRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w, x, y);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
 				}
 				else if (hvy<0)
 				{
 					Rect srcRect = genRect(arrows->ourImages[pn].bitmap->h, arrows->ourImages[pn].bitmap->w-hvx, 0, 0);
 					Rect dstRect = genRect(arrows->ourImages[pn].bitmap->h, arrows->ourImages[pn].bitmap->w-hvx, x, y);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
 				}
 				else
 				{
 					Rect srcRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w-hvx, 0, 0);
 					Rect dstRect = genRect(arrows->ourImages[pn].bitmap->h-hvy, arrows->ourImages[pn].bitmap->w-hvx, x, y);
-					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(arrows->ourImages[pn].bitmap, &srcRect, to, &dstRect);
 				}
 			}
 			SDL_SetClipRect(to, &prevClip);
@@ -255,15 +255,15 @@ void CTerrainRect::showPath(const SDL_Rect * extRect, SDL_Surface * to)
 void CTerrainRect::show()
 {
 	if(ADVOPT.smoothMove)
-		CGI->mh->terrainRect
-			(adventureInt->position, adventureInt->anim,
-			 &LOCPLINT->cb->getVisibilityMap(), true, adventureInt->heroAnim,
-			 nullptr, &pos, moveX, moveY, false, int3());
+		CGI->mh->terrainRect(
+			adventureInt->position, adventureInt->anim,
+			&LOCPLINT->cb->getVisibilityMap(), true, adventureInt->heroAnim,
+			nullptr, &pos, moveX, moveY, false, int3());
 	else
-		CGI->mh->terrainRect
-			(adventureInt->position, adventureInt->anim,
-			 &LOCPLINT->cb->getVisibilityMap(), true, adventureInt->heroAnim,
-			 nullptr, &pos, 0, 0, false, int3());
+		CGI->mh->terrainRect(
+			adventureInt->position, adventureInt->anim,
+			&LOCPLINT->cb->getVisibilityMap(), true, adventureInt->heroAnim,
+			nullptr, &pos, 0, 0, false, int3());
 
 	//SDL_BlitSurface(teren,&genRect(pos.h,pos.w,0,0),screen,&genRect(547,594,7,6));
 	//SDL_FreeSurface(teren);
@@ -414,12 +414,11 @@ infoBar(Rect(ADVOPT.infoboxX, ADVOPT.infoboxY, 192, 192) )
 	heroAnim=0;
 	heroAnimValHitCount=0; // hero animation frame
 
-	for (int g=0; g<ADVOPT.gemG.size(); ++g)
+	for (size_t g=0; g<ADVOPT.gemG.size(); ++g)
 	{
 		gems.push_back(CDefHandler::giveDef(ADVOPT.gemG[g]));
 	}
-
-
+	
 	setPlayer(LOCPLINT->playerID);
 	underground.block(!CGI->mh->map->twoLevel);
 	addUsedEvents(MOVE);
@@ -429,8 +428,7 @@ CAdvMapInt::~CAdvMapInt()
 {
 	SDL_FreeSurface(bg);
 
-	for(int i=0; i<gems.size(); i++)
-		delete gems[i];
+	for(size_t i=0; i<gems.size(); ++i) delete gems[i];
 }
 
 void CAdvMapInt::fshowOverview()
@@ -524,7 +522,7 @@ void CAdvMapInt::fendTurn()
 
 	if ( settings["adventure"]["heroReminder"].Bool())
 	{
-		for (int i = 0; i < LOCPLINT->wanderingHeroes.size(); i++)
+		for (size_t i = 0; i < LOCPLINT->wanderingHeroes.size(); ++i)
 			if (!isHeroSleeping(LOCPLINT->wanderingHeroes[i]) && (LOCPLINT->wanderingHeroes[i]->movement > 0))
 			{
 				LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[55], boost::bind(&CAdvMapInt::endingTurn, this), 0, false);
@@ -1430,7 +1428,8 @@ void CAdvMapInt::tileRClicked(const int3 &mapPos)
 		return;
 	}
 
-	CRClickPopup::createAndPush(obj, GH.current->motion, CENTER);
+	auto &motion = GH.current->motion;
+	CRClickPopup::createAndPush(obj, Point(motion.x, motion.y), CENTER);
 }
 
 void CAdvMapInt::enterCastingMode(const CSpell * sp)

+ 4 - 4
client/CAnimation.cpp

@@ -648,7 +648,7 @@ void SDLImage::draw(SDL_Surface *where, int posX, int posY, Rect *src, ui8 rotat
 	Rect destRect(posX, posY, surf->w, surf->h);
 	destRect += sourceRect.topLeft();
 	sourceRect -= margins;
-	CSDL_Ext::blitSurface(surf, &sourceRect, where, &destRect);
+//*	CSDL_Ext::blitSurface(surf, &sourceRect, where, &destRect);
 }
 
 void SDLImage::playerColored(PlayerColor player)
@@ -998,7 +998,7 @@ void CAnimation::init(CDefFile * file)
 
 		BOOST_FOREACH(const JsonNode &group, config["sequences"].Vector())
 		{
-			size_t groupID = group["group"].Float();//TODO: string-to-value conversion("moving" -> MOVING)
+			size_t groupID = group["group"].asInteger();//TODO: string-to-value conversion("moving" -> MOVING)
 			source[groupID].clear();
 
 			BOOST_FOREACH(const JsonNode &frame, group["frames"].Vector())
@@ -1011,8 +1011,8 @@ void CAnimation::init(CDefFile * file)
 
 		BOOST_FOREACH(const JsonNode &node, config["images"].Vector())
 		{
-			size_t group = node["group"].Float();
-			size_t frame = node["frame"].Float();
+			size_t group = node["group"].asInteger();
+			size_t frame = node["frame"].asInteger();
 
 			if (source[group].size() <= frame)
 				source[group].resize(frame+1);

+ 2 - 2
client/CBitmapHandler.cpp

@@ -56,7 +56,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
 		ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 8, 0, 0, 0, 0);
 
 		it = 0xC;
-		for (int i=0; i<height; i++)
+		for (size_t i=0; i<height; ++i)
 		{
 			memcpy((char*)ret->pixels + ret->pitch * i, pcx + it, width);
 			it+= width;
@@ -88,7 +88,7 @@ SDL_Surface * BitmapHandler::loadH3PCX(ui8 * pcx, size_t size)
 		ret = SDL_CreateRGBSurface(SDL_SWSURFACE, width, height, 24, rmask, gmask, bmask, 0);
 
 		//it == 0xC;
-		for (int i=0; i<height; i++)
+		for (size_t i=0; i<height; ++i)
 		{
 			memcpy((char*)ret->pixels + ret->pitch * i, pcx + it, width*3);
 			it+= width*3;

+ 0 - 1
client/CCastleInterface.cpp

@@ -1661,7 +1661,6 @@ CBlacksmithDialog::CBlacksmithDialog(bool possible, CreatureID creMachineID, Art
 //*	statusBar = new CGStatusBar(new CPicture(*background, Rect(8, pos.h - 26, pos.w - 16, 19), 8, pos.h - 26));
 	
 	animBG = new CPicture("TPSMITBK", 64, 50);
-	animBG->needRefresh = true;
 
 	const CCreature *creature = CGI->creh->creatures[creMachineID];
 	anim = new CCreatureAnim(64, 50, creature->animDefName, Rect());

+ 6 - 7
client/CCreatureWindow.cpp

@@ -300,11 +300,11 @@ void CCreatureWindow::init(const CStackInstance *Stack, const CBonusSystemNode *
 	if (type >= COMMANDER)
 	{
 		setBackground("CommWin" + boost::lexical_cast<std::string>(bonusRows) + ".pcx");
-		for (int i = 0; i < skillPictures.size(); ++i)
+		for (size_t i = 0; i < skillPictures.size(); ++i)
 		{
 			skillPictures[i]->moveTo (Point (pos.x + 37 + i * 84, pos.y + 224));
 		}
-		for (int i = 0; i < selectableSkills.size(); ++i)
+		for (size_t i = 0; i < selectableSkills.size(); ++i)
 		{
 			if (upgradeOptions[i] < skillPictures.size()) // it's secondary skill
 			{
@@ -547,15 +547,15 @@ void CCreatureWindow::showAll()
 	BOOST_FOREACH(auto s, selectableSkills)
 		s->showAll();
 
-	for (int i = 0; i < skillPictures.size(); i++)
+	for (size_t i = 0; i < skillPictures.size(); ++i)
 	{
 //*		skillPictures[i]->bg = BitmapHandler::loadBitmap (skillToFile(i));
-//*		skillPictures[i]->showAll (to);
+//*		skillPictures[i]->showAll();
 	}
 
 	if (upgradeOptions.size() && (type == COMMANDER_LEVEL_UP && upgradeOptions[selectedOption] >= 100)) //add frame to selected skill
 	{
-//		int index = selectedOption - selectableSkills.size(); //this is screwed
+//*		int index = selectedOption - selectableSkills.size(); //this is screwed
 //*		CSDL_Ext::drawBorder(to, Rect::around(selectableBonuses[index]->pos), int3(Colors::METALLIC_GOLD.r, Colors::METALLIC_GOLD.g, Colors::METALLIC_GOLD.b)); 
 	}
 }
@@ -684,8 +684,7 @@ void CCreatureWindow::selectSkill (ui32 which)
 
 CCreatureWindow::~CCreatureWindow()
 {
- 	for (int i=0; i<upgResCost.size(); ++i)
- 		delete upgResCost[i];
+ 	for (size_t i=0; i<upgResCost.size(); ++i) delete upgResCost[i];
 	bonusItems.clear();
 }
 

+ 1 - 1
client/CHeroWindow.cpp

@@ -145,7 +145,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
 	luck = new MoraleLuckBox(false, Rect(233,179,53,45));
 	spellPointsArea = new LRClickableAreaWText(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]);
 
-	for(int i = 0; i < std::min<size_t>(hero->secSkills.size(), 8u); ++i)
+	for(size_t i = 0; i < std::min<size_t>(hero->secSkills.size(), 8u); ++i)
 	{
 		Rect r = Rect(i%2 == 0  ?  18  :  162,  276 + 48 * (i/2),  136,  42);
 		secSkillAreas.push_back(new LRClickableAreaWTextComp(r, CComponent::secskill));

+ 2 - 0
client/CKingdomInterface.cpp

@@ -63,6 +63,7 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data)
 		name = new CLabel(pos.w+6, 6, font, TOPLEFT, Colors::WHITE, data->getNameText());
 		value = new CLabel(pos.w+6, pos.h-16, font, TOPLEFT, Colors::WHITE, data->getValueText());
 	}
+/*
 	pos = image->pos;
 	if (name)
 		pos = pos | name->pos;
@@ -72,6 +73,7 @@ InfoBox::InfoBox(Point position, InfoPos Pos, InfoSize Size, IInfoBoxData *Data)
 	hover = new CHoverableArea;
 	hover->hoverText = data->getHoverText();
 	hover->pos = pos;
+*/
 }
 
 InfoBox::~InfoBox()

+ 28 - 11
client/CMT.cpp

@@ -77,7 +77,6 @@ static bool gOnlyAI = false;
 
 static bool ermInteractiveMode = false; //structurize when time is right
 void processCommand(const std::string &message);
-//static void setScreenRes(int w, int h, int bpp, bool fullscreen, bool resetVideo=true);
 void dispose();
 void playIntro();
 static void listenForEvents();
@@ -252,7 +251,7 @@ int main(int argc, char* argv[])
 	}
 
 	//Set environment vars to make window centered. Sometimes work, sometimes not. :/
-	putenv((char*)"SDL_VIDEO_CENTERED=center");
+	putenv("SDL_VIDEO_CENTERED=center");
 	//putenv("SDL_VIDEO_WINDOW_POS");
 
 	// Have effect on X11 system only (Linux).
@@ -272,6 +271,26 @@ int main(int argc, char* argv[])
 
 	preinitDLL(::console, logfile);
 
+	// Some basic data validation to produce better error messages in cases of incorrect install
+	auto testFile = [](std::string filename, std::string message) -> bool
+	{
+		if (CResourceHandler::get()->existsResource(ResourceID(filename)))
+			return true;
+
+		tlog1 << "Error: " << message << " was not found!\n";
+		return false;
+	};
+
+	if (!testFile("DATA/HELP.TXT", "Heroes III data") &&
+	    !testFile("DATA/ZELP.TXT", "In the Wake of Gods data") &&
+	    !testFile("MODS/VCMI/MOD.JSON", "VCMI mod") &&
+	    !testFile("DATA/StackQueueBgBig.PCX", "VCMI data"))
+		exit(1); // These are unrecoverable errors
+
+	// these two are optional + some installs have them on CD and not in data directory
+	testFile("VIDEO/GOOD1A.SMK", "campaign movies");
+	testFile("SOUNDS/G1A.WAV", "campaign music"); //technically not a music but voiced intro sounds
+
 	settings.init();
 	conf.init();
 	tlog0 <<"Loading settings: "<<pomtime.getDiff() << std::endl;
@@ -308,16 +327,14 @@ int main(int argc, char* argv[])
 	tlog0 <<"\tInitializing screen: "<<pomtime.getDiff() << std::endl;
 
 	// Initialize video
-
-//TODO: video support for OpenGL
-//#if DISABLE_VIDEO
-//	CCS->videoh = new CEmptyVideoPlayer;
-//#else
-//	if (!vm.count("disable-video"))
-//		CCS->videoh = new CVideoPlayer;
-//	else
+#if DISABLE_VIDEO
+	CCS->videoh = new CEmptyVideoPlayer;
+#else
+	if (!vm.count("disable-video"))
+		CCS->videoh = new CVideoPlayer;
+	else
 		CCS->videoh = new CEmptyVideoPlayer;
-//#endif
+#endif
 
 	tlog0<<"\tInitializing video: "<<pomtime.getDiff()<<std::endl;
 

+ 9 - 9
client/CMessage.cpp

@@ -226,7 +226,7 @@ void CMessage::drawIWindow(CInfoWindow * ret, std::string text, PlayerColor play
 	if(dynamic_cast<CSelWindow*>(ret)) //it's selection window, so we'll blit "or" between components
 		blitOr = true;
 
-	const int sizes[][2] = {{400, 125}, {500, 150}, {600, 200}, {480, 400}};
+	const ui32 sizes[][2] = {{400, 125}, {500, 150}, {600, 200}, {480, 400}};
 
 	for(int i = 0; 
 		i < ARRAY_COUNT(sizes) 
@@ -323,11 +323,11 @@ void CMessage::drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int
 		// Top border
 		Rect srcR(0, 0, cur_w, box[6]->h);
 		Rect dstR(start_x, y, 0, 0);
-		CSDL_Ext::blitSurface(box[6], &srcR, ret, &dstR);
+//*		CSDL_Ext::blitSurface(box[6], &srcR, ret, &dstR);
 		
 		// Bottom border
 		dstR.y = bottom_y;
-		CSDL_Ext::blitSurface(box[7], &srcR, ret, &dstR);
+//*		CSDL_Ext::blitSurface(box[7], &srcR, ret, &dstR);
 
 		start_x += cur_w;
 	}
@@ -344,27 +344,27 @@ void CMessage::drawBorder(PlayerColor playerColor, SDL_Surface * ret, int w, int
 		// Left border
 		Rect srcR(0, 0, box[4]->w, cur_h);
 		Rect dstR(x, start_y, 0, 0);
-		CSDL_Ext::blitSurface(box[4], &srcR, ret, &dstR);
+//*		CSDL_Ext::blitSurface(box[4], &srcR, ret, &dstR);
 
 		// Right border
 		dstR.x = right_x;
-		CSDL_Ext::blitSurface(box[5], &srcR, ret, &dstR);
+//*		CSDL_Ext::blitSurface(box[5], &srcR, ret, &dstR);
 
 		start_y += cur_h;
 	}
 
 	//corners
 	Rect dstR(x, y, box[0]->w, box[0]->h);
-	CSDL_Ext::blitSurface(box[0], NULL, ret, &dstR);
+//*	CSDL_Ext::blitSurface(box[0], NULL, ret, &dstR);
 
 	dstR=Rect(x+w-box[1]->w, y,   box[1]->w, box[1]->h);
-	CSDL_Ext::blitSurface(box[1], NULL, ret, &dstR);
+//*	CSDL_Ext::blitSurface(box[1], NULL, ret, &dstR);
 
 	dstR=Rect(x, y+h-box[2]->h+1, box[2]->w, box[2]->h);
-	CSDL_Ext::blitSurface(box[2], NULL, ret, &dstR);
+//*	CSDL_Ext::blitSurface(box[2], NULL, ret, &dstR);
 
 	dstR=Rect(x+w-box[3]->w, y+h-box[3]->h+1, box[3]->w, box[3]->h);
-	CSDL_Ext::blitSurface(box[3], NULL, ret, &dstR);
+//*	CSDL_Ext::blitSurface(box[3], NULL, ret, &dstR);
 }
 
 ComponentResolved::ComponentResolved( CComponent *Comp ):

+ 5 - 5
client/CPlayerInterface.cpp

@@ -88,7 +88,7 @@ int CPlayerInterface::howManyPeople = 0;
 
 struct OCM_HLP_CGIN
 {
-	bool inline operator ()(const std::pair<const CGObjectInstance*,SDL_Rect>  & a, const std::pair<const CGObjectInstance*,SDL_Rect> & b) const
+	bool inline operator ()(const std::pair<const CGObjectInstance*,Rect>  & a, const std::pair<const CGObjectInstance*,Rect> & b) const
 	{
 		return (*a.first)<(*b.first);
 	}
@@ -202,10 +202,10 @@ void CPlayerInterface::yourTurn()
 	acceptTurn();
 }
 
-STRONG_INLINE void subRect(const int & x, const int & y, const int & z, const SDL_Rect & r, const ObjectInstanceID & hid)
+STRONG_INLINE void subRect(const int & x, const int & y, const int & z, const Rect & r, const ObjectInstanceID & hid)
 {
 	TerrainTile2 & hlp = CGI->mh->ttiles[x][y][z];
-	for(int h=0; h<hlp.objects.size(); ++h)
+	for(size_t h=0; h<hlp.objects.size(); ++h)
 		if(hlp.objects[h].first->id == hid)
 		{
 			hlp.objects[h].second = r;
@@ -239,7 +239,7 @@ void CPlayerInterface::heroMoved(const TryMoveHero & details)
 		//TODO very evil workaround -> retreive pointer to hero so we could animate it
 		// TODO -> we should not need full CGHeroInstance structure to display animation or it should not be handled by playerint (but by the client itself)
 		const TerrainTile2 &tile = CGI->mh->ttiles[hp.x-1][hp.y][hp.z];
-		for(int i = 0; i < tile.objects.size(); i++)
+		for(size_t i = 0; i < tile.objects.size(); ++i)
 			if(tile.objects[i].first->id == details.id)
 				ho = dynamic_cast<const CGHeroInstance *>(tile.objects[i].first);
 
@@ -617,7 +617,7 @@ void CPlayerInterface::battleStacksHealedRes(const std::vector<std::pair<ui32, u
 		return;
 	}
 
-	for(int b=0; b<healedStacks.size(); ++b)
+	for(size_t b=0; b<healedStacks.size(); ++b)
 	{
 		const CStack * healed = cb->battleGetStackByID(healedStacks[b].first);
 		if(battleInt->creAnims[healed->ID]->getType() == CCreatureAnim::DEATH)

+ 23 - 29
client/CPreGame.cpp

@@ -381,7 +381,7 @@ CButton* CMenuEntry::createButton(CMenuScreen* parent, const JsonNode& button)
 	const PairOfStrings * help = (button["help"].Float() > 0) ?
 		&( CGI->generaltexth->zelp[button["help"].asInteger()] ) : nullptr;
 
-	return new CButton(command, point, button["name"].String(), 0, 4, help, LCLICK|RCLICK|HOVER|KEYBOARD, button["hotkey"].asInteger());
+	return new CButton(command, point, button["name"].String(), 0, 4, help, button["hotkey"].asInteger());
 }
 
 CMenuEntry::CMenuEntry(CMenuScreen* parent, const JsonNode &config)
@@ -430,12 +430,12 @@ void CreditsScreen::show()
 		count = 0;
 	}
 	Rect creditsArea = credits->pos & pos;
-	SDL_SetClipRect(screenBuf, &creditsArea);
-	SDL_SetClipRect(screen, &creditsArea);
+//*	SDL_SetClipRect(screenBuf, &creditsArea);
+//*	SDL_SetClipRect(screen, &creditsArea);
 	redraw();
 	CIntObject::showAll();
-	SDL_SetClipRect(screen, NULL);
-	SDL_SetClipRect(screenBuf, NULL);
+//*	SDL_SetClipRect(screen, NULL);
+//*	SDL_SetClipRect(screenBuf, NULL);
 
 	//end of credits, close this screen
 	if (credits->pos.y + credits->pos.h < 0)
@@ -620,7 +620,7 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMulti
 				toggleTab(sel);
 				changeSelection(sel->getSelectedMapInfo());
 			};
-			CButton * select = new CButton(selectCmd, Gfx::Point(411, 80), "GSPBUTT", 0, 4, &(zelp[45]), LCLICK|RCLICK|KEYBOARD, SDLK_s);
+			CButton * select = new CButton(selectCmd, Gfx::Point(411, 80), "GSPBUTT", 0, 4, &(zelp[45]), SDLK_s);
 			select->addTextOverlay(CGI->generaltexth->allTexts[500], FONT_SMALL);
 
 			const CFunctionList<void()> randomCmd = [&]()
@@ -628,13 +628,13 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMulti
 				toggleTab(randMapTab);
 				changeSelection(&randMapTab->getMapInfo());
 			};
-			CButton * randomBtn = new CButton(randomCmd, Gfx::Point(411, 105), "GSPBUTT", 0, 4, &(zelp[47]), LCLICK|RCLICK|KEYBOARD, SDLK_r);
+			CButton * randomBtn = new CButton(randomCmd, Gfx::Point(411, 105), "GSPBUTT", 0, 4, &(zelp[47]), SDLK_r);
 			randomBtn->addTextOverlay(CGI->generaltexth->allTexts[740], FONT_SMALL);
 
-			CButton * opts = new CButton(bind(&CSelectionScreen::toggleTab, this, opt), Gfx::Point(411, 510), "GSPBUTT", 0, 4, &(zelp[46]), LCLICK|RCLICK|KEYBOARD, SDLK_a);
+			CButton * opts = new CButton(bind(&CSelectionScreen::toggleTab, this, opt), Gfx::Point(411, 510), "GSPBUTT", 0, 4, &(zelp[46]), SDLK_a);
 			opts->addTextOverlay(CGI->generaltexth->allTexts[501], FONT_SMALL);
 
-			start = new CButton(bind(&CSelectionScreen::startScenario, this), Gfx::Point(411, 535), "SCNRBEG", 0, 4, &(zelp[103]), LCLICK|RCLICK|KEYBOARD, SDLK_b);
+			start = new CButton(bind(&CSelectionScreen::startScenario, this), Gfx::Point(411, 535), "SCNRBEG", 0, 4, &(zelp[103]), SDLK_b);
 
 			if(network)
 			{
@@ -655,21 +655,21 @@ CSelectionScreen::CSelectionScreen(CMenuScreen::EState Type, CMenuScreen::EMulti
 		break;
 	case CMenuScreen::loadGame:
 		sel->recActions = 255;
-		start = new CButton(bind(&CSelectionScreen::startScenario, this), Gfx::Point(411, 535), "SCNRLOD", 0, 4, &(zelp[103]), LCLICK|RCLICK|KEYBOARD, SDLK_l);
+		start = new CButton(bind(&CSelectionScreen::startScenario, this), Gfx::Point(411, 535), "SCNRLOD", 0, 4, &(zelp[103]), SDLK_l);
 		break;
 	case CMenuScreen::saveGame:
 		sel->recActions = 255;
-		start = new CButton(bind(&CSelectionScreen::startScenario, this), Gfx::Point(411, 535), "SCNRSAV", 0, 4, &(zelp[103]), LCLICK|RCLICK|KEYBOARD);
+		start = new CButton(bind(&CSelectionScreen::startScenario, this), Gfx::Point(411, 535), "SCNRSAV", 0, 4, &(zelp[103]));
 		break;
 	case CMenuScreen::campaignList:
 		sel->recActions = 255;
-		start = new CButton(bind(&CSelectionScreen::startCampaign, this), Gfx::Point(411, 535), "SCNRLOD", 0, 4, nullptr, LCLICK|RCLICK|KEYBOARD, SDLK_b);
+		start = new CButton(bind(&CSelectionScreen::startCampaign, this), Gfx::Point(411, 535), "SCNRLOD", 0, 4, nullptr, SDLK_b);
 		break;
 	}
 
 	start->assignedKeys.insert(SDLK_RETURN);
 
-	back = new CButton( bind(&CGuiHandler::popIntTotally, &GH, this), Gfx::Point(581, 535), "SCNRBACK", 0, 2, &(zelp[105]), LCLICK|RCLICK|KEYBOARD, SDLK_ESCAPE);
+	back = new CButton( bind(&CGuiHandler::popIntTotally, &GH, this), Gfx::Point(581, 535), "SCNRBACK", 0, 2, &(zelp[105]), SDLK_ESCAPE);
 
 	if(network)
 	{
@@ -1234,7 +1234,6 @@ SelectionTab::SelectionTab(CMenuScreen::EState Type, const boost::function<void(
 
 	slider = new CSlider(372, 86, tabType != CMenuScreen::saveGame ? 480 : 430, bind(&SelectionTab::sliderMove, this, _1), positions, curItems.size(), 0, false, 1);
 	slider->addUsedEvents(WHEEL);
-//*	slider->slider->keepFrame = true;
 	format =  CDefHandler::giveDef("SCSELC.DEF");
 
 	sortingBy = _format;
@@ -1536,7 +1535,7 @@ int SelectionTab::getLine()
 {
 	int line = -1;
 	Point clickPos(GH.current->button.x, GH.current->button.y);
-	clickPos = clickPos - pos.topLeft();
+	clickPos -= pos;
 
 	if (clickPos.y > 115  &&  clickPos.y < 564  &&  clickPos.x > 22  &&  clickPos.x < 371)
 	{
@@ -1895,12 +1894,7 @@ InfoCard::InfoCard( bool Network )
 	Rect descriptionRect(26, 149, 320, 115);
 	mapDescription = new CTextBox("", descriptionRect, 1);
 
-	if(SEL->screenType == CMenuScreen::campaignList)
-	{
-		CSelectionScreen *ss = static_cast<CSelectionScreen*>(parent);
-		mapDescription->addChild(new CPicture(ss->bg->getImage(), descriptionRect + Point(-393, 0)), true); //move subpicture bg to our description control (by default it's our (Infocard) child)
-	}
-	else
+	if(SEL->screenType != CMenuScreen::campaignList)
 	{
 		bg = new CPicture("GSELPOP1.bmp", 0, 0);
 		parent->addChild(bg);
@@ -1913,7 +1907,7 @@ InfoCard::InfoCard( bool Network )
 		sFlags = CDefHandler::giveDef("ITGFLAGS.DEF");
 		difficulty = new CHighlightableButtonsGroup(0);
 		{
-			static const char *difButns[] = {"GSPBUT3.DEF", "GSPBUT4.DEF", "GSPBUT5.DEF", "GSPBUT6.DEF", "GSPBUT7.DEF"};
+			static const char *difButns[] = {"GSPBUT3", "GSPBUT4", "GSPBUT5", "GSPBUT6", "GSPBUT7"};
 
 			for(int i = 0; i < 5; i++)
 			{
@@ -1924,14 +1918,14 @@ InfoCard::InfoCard( bool Network )
 		if(SEL->screenType != CMenuScreen::newGame)
 			difficulty->block(true);
 
-		//description needs bg
-		mapDescription->addChild(new CPicture(bg->getImage(), descriptionRect), true); //move subpicture bg to our description control (by default it's our (Infocard) child)
-
-		if(network)
+		if (network)
 		{
 			playerListBg = new CPicture("CHATPLUG.bmp", 16, 276);
+
+			Rect tmp_rect = chat->chatHistory->pos;
+			tmp_rect -= pos;
 			chat = new CChatBox(descriptionRect);
-			chat->chatHistory->addChild(new CPicture(bg->getImage(), chat->chatHistory->pos - pos), true); //move subpicture bg to our description control (by default it's our (Infocard) child)
+			chat->chatHistory->addChild(new CPicture(bg->getImage(), tmp_rect), true); //move subpicture bg to our description control (by default it's our (Infocard) child)
 
 			chatOn = true;
 			mapDescription->disable();
@@ -2020,7 +2014,7 @@ void InfoCard::showAll()
 
 			//difficulty
 			assert(SEL->current->mapHeader->difficulty <= 4);
-//			std::string &diff = CGI->generaltexth->arraytxt[142 + SEL->current->mapHeader->difficulty];
+			std::string &diff = CGI->generaltexth->arraytxt[142 + SEL->current->mapHeader->difficulty];
 //*			printAtMiddleLoc(diff, 62, 472, FONT_SMALL, Colors::WHITE, to);
 
 			//selecting size icon
@@ -4068,7 +4062,7 @@ CPrologEpilogVideo::CPrologEpilogVideo( CCampaignScenario::SScenarioPrologEpilog
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	addUsedEvents(LCLICK);
-	pos = Rect(screen);
+	pos = Rect(0, 0, GL2D::getScreenWidth(), GL2D::getScreenHeight());
 
 	CCS->videoh->open(CCampaignHandler::prologVideoName(spe.prologVideo));
 

+ 5 - 5
client/CSpellWindow.cpp

@@ -32,7 +32,7 @@
 
 extern SDL_Surface * screen;
 
-SpellbookInteractiveArea::SpellbookInteractiveArea(const SDL_Rect & myRect, boost::function<void()> funcL,
+SpellbookInteractiveArea::SpellbookInteractiveArea(const Rect & myRect, boost::function<void()> funcL,
 	const std::string & textR, boost::function<void()> funcHon, boost::function<void()> funcHoff, CPlayerInterface * _myInt)
 {
 	addUsedEvents(LCLICK | RCLICK | HOVER);
@@ -70,7 +70,7 @@ void SpellbookInteractiveArea::hover(bool on)
 	}
 }
 
-CSpellWindow::CSpellWindow(const SDL_Rect &, const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells):
+CSpellWindow::CSpellWindow(const Rect &, const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells):
     CWindowObject(PLAYER_COLORED, "SpelBack"),
 	battleSpellsOnly(openOnBattleSpells),
 	selectedTab(4),
@@ -159,7 +159,7 @@ CSpellWindow::CSpellWindow(const SDL_Rect &, const CGHeroInstance * _myHero, CPl
 
 
 	statusBar = new CGStatusBar(7 + pos.x, 569 + pos.y, "Spelroll.bmp");
-	SDL_Rect temp_rect = genRect(45, 35, 479 + pos.x, 405 + pos.y);
+	Rect temp_rect = genRect(45, 35, 479 + pos.x, 405 + pos.y);
 	exitBtn = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fexitb, this), CGI->generaltexth->zelp[460].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[460].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt);
 	temp_rect = genRect(45, 35, 221 + pos.x, 405 + pos.y);
 	battleSpells = new SpellbookInteractiveArea(temp_rect, boost::bind(&CSpellWindow::fbattleSpellsb, this), CGI->generaltexth->zelp[453].second, boost::bind(&CGStatusBar::print, statusBar, (CGI->generaltexth->zelp[453].first)), boost::bind(&CGStatusBar::clear, statusBar), myInt);
@@ -590,7 +590,7 @@ void CSpellWindow::teleportTo( int town, const CGHeroInstance * hero )
 	LOCPLINT->cb->castSpell(hero, SpellID::TOWN_PORTAL, dest->visitablePos());
 }
 
-CSpellWindow::SpellArea::SpellArea(SDL_Rect pos, CSpellWindow * owner)
+CSpellWindow::SpellArea::SpellArea(const Rect &pos, CSpellWindow * owner)
 {
 	this->pos = pos;
 	this->owner = owner;
@@ -828,7 +828,7 @@ void CSpellWindow::SpellArea::showAll()
 	if(mySpell < 0)
 		return;
 
-//	const CSpell * spell = mySpell.toSpell();
+	const CSpell * spell = mySpell.toSpell();
 
 //*	blitAt(owner->spells->ourImages[mySpell].bitmap, pos.x, pos.y, to);
 //*	blitAt(owner->schoolBorders[owner->selectedTab >= 4 ? whichSchool : owner->selectedTab]->ourImages[schoolLevel].bitmap, pos.x, pos.y, to); //printing border (indicates level of magic school)

+ 3 - 3
client/CSpellWindow.h

@@ -34,7 +34,7 @@ public:
 	void clickRight(tribool down, bool previousState);
 	void hover(bool on);
 
-	SpellbookInteractiveArea(const SDL_Rect & myRect, boost::function<void()> funcL, const std::string & textR,
+	SpellbookInteractiveArea(const Rect & myRect, boost::function<void()> funcL, const std::string & textR,
 		boost::function<void()> funcHon, boost::function<void()> funcHoff, CPlayerInterface * _myInt);//c-tor
 };
 
@@ -51,7 +51,7 @@ private:
 		int spellCost;
 		CSpellWindow * owner;
 
-		SpellArea(SDL_Rect pos, CSpellWindow * owner);
+		SpellArea(const Rect &pos, CSpellWindow * owner);
 
 		void setSpell(SpellID spellID);
 
@@ -92,7 +92,7 @@ private:
 
 public:
 
-	CSpellWindow(const SDL_Rect & myRect, const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells = true); //c-tor
+	CSpellWindow(const Rect & myRect, const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells = true); //c-tor
 	~CSpellWindow(); //d-tor
 
 	void fexitb();

+ 2 - 2
client/FunctionList.h

@@ -66,7 +66,7 @@ public:
 	void operator()(const Arg & a) const
 	{
 		std::vector<boost::function<Signature> > funcs2 = funcs; //backup
-		for(int i=0;i<funcs2.size(); i++) 
+		for(size_t i=0; i<funcs2.size(); ++i) 
 		{
 			if (funcs2[i])
 				funcs2[i](a);
@@ -77,7 +77,7 @@ public:
 	void operator()(Arg1 & a, Arg2 & b) const
 	{
 		std::vector<boost::function<Signature> > funcs2 = funcs; //backup
-		for(int i=0;i<funcs2.size(); i++)
+		for(size_t i=0; i<funcs2.size(); ++i)
 		{
 			if (funcs2[i])
 				funcs2[i](a, b);

+ 23 - 20
client/GUIClasses.cpp

@@ -1195,7 +1195,9 @@ void CComponentBox::placeComponents(bool selectable)
 			{
 				if (selectable)
 				{
-					Point orPos = Point(currentX - freeSpace, currentY) + getOrTextPos(prevComp, *iter);
+					Point orPos = getOrTextPos(prevComp, *iter);
+					orPos.x += currentX - freeSpace;
+					orPos.y += currentY;
 
 					new CLabel(orPos.x, orPos.y, FONT_MEDIUM, CENTER, Colors::WHITE, CGI->generaltexth->allTexts[4]);
 				}
@@ -1217,7 +1219,7 @@ CComponentBox::CComponentBox(CComponent * _components, Rect position):
     selected(nullptr)
 {
 	type |= REDRAW_PARENT;
-	pos = position + pos;
+	pos.addOffs_copySize(position);
 	placeComponents(false);
 }
 
@@ -1226,7 +1228,7 @@ CComponentBox::CComponentBox(std::vector<CComponent *> _components, Rect positio
     selected(nullptr)
 {
 	type |= REDRAW_PARENT;
-	pos = position + pos;
+	pos.addOffs_copySize(position);
 	placeComponents(false);
 }
 
@@ -1236,7 +1238,7 @@ CComponentBox::CComponentBox(std::vector<CSelectableComponent *> _components, Re
     onSelect(_onSelect)
 {
 	type |= REDRAW_PARENT;
-	pos = position + pos;
+	pos.addOffs_copySize(position);
 	placeComponents(true);
 
 	assert(!components.empty());
@@ -1323,7 +1325,6 @@ CCreaturePic::CCreaturePic(int x, int y, const CCreature *cre, bool Big, bool An
 		bg = new CPicture(CGI->townh->factions[faction].creatureBg130);
 	else
 		bg = new CPicture(CGI->townh->factions[faction].creatureBg120);
-	bg->needRefresh = true;
 	anim = new CCreatureAnim(0, 0, cre->animDefName, Rect());
 	anim->clipRect(cre->isDoubleWide()?170:150, 155, bg->pos.w, bg->pos.h);
 	anim->startPreview(cre->hasBonusOfType(Bonus::SIEGE_WEAPON));
@@ -1376,7 +1377,7 @@ void CRecruitmentWindow::CCreatureCard::showAll()
 CRecruitmentWindow::CCostBox::CCostBox(Rect position, std::string title)
 {
 	type |= REDRAW_PARENT;
-	pos = position + pos;
+	pos.addOffs_copySize(position);
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 	new CLabel(pos.w/2, 10, FONT_SMALL, CENTER, Colors::WHITE, title);
 }
@@ -2062,7 +2063,7 @@ void CTradeWindow::CTradeableItem::showAll()
 
 	if (image)
 	{
-		image->moveTo(pos.topLeft() + posToBitmap);
+		image->moveTo(posToBitmap += pos);
 		CIntObject::showAll();
 	}
 
@@ -2325,7 +2326,8 @@ void CTradeWindow::initItems(bool Left)
 			continue;
 
 		CTradeableItem *hlp = new CTradeableItem(pos[j].topLeft(), itemsType[Left], id, Left, j);
-		hlp->pos = pos[j] + this->pos.topLeft();
+		hlp->pos = pos[j];
+		hlp->pos += this->pos;
 		items[Left].push_back(hlp);
 	}
 
@@ -3209,7 +3211,8 @@ void CAltarWindow::mimicCres()
 	BOOST_FOREACH(CTradeableItem *t, items[1])
 	{
 		CTradeableItem *hlp = new CTradeableItem(positions[t->serial].topLeft(), CREATURE_PLACEHOLDER, t->id, false, t->serial);
-		hlp->pos = positions[t->serial] + this->pos.topLeft();
+		hlp->pos = positions[t->serial];
+		hlp->pos += this->pos;
 		items[0].push_back(hlp);
 	}
 }
@@ -3712,7 +3715,7 @@ CTavernWindow::~CTavernWindow()
 	CCS->videoh->close();
 }
 
-void CTavernWindow::show(SDL_Surface * to)
+void CTavernWindow::show()
 {
 //*	CWindowObject::show(to);
 
@@ -3731,7 +3734,7 @@ void CTavernWindow::show(SDL_Surface * to)
 			boost::algorithm::replace_first(recruit->hoverTexts[0],"%s",sel->h->type->heroClass->name);
 		}
 
-		printAtMiddleWBLoc(sel->descr, 146, 395, FONT_SMALL, 200, Colors::WHITE, to);
+//*		printAtMiddleWBLoc(sel->descr, 146, 395, FONT_SMALL, 200, Colors::WHITE, to);
 //*		CSDL_Ext::drawBorder(to,sel->pos.x-2,sel->pos.y-2,sel->pos.w+4,sel->pos.h+4,int3(247,223,123));
 	}
 }
@@ -3787,7 +3790,7 @@ void CTavernWindow::HeroPortrait::hover( bool on )
 		GH.statusbar->clear();
 }
 
-void CInGameConsole::show(SDL_Surface * to)
+void CInGameConsole::show()
 {
 	int number = 0;
 
@@ -3801,8 +3804,8 @@ void CInGameConsole::show(SDL_Surface * to)
 		{
 			leftBottomCorner = LOCPLINT->battleInt->pos.bottomLeft();
 		}
-		graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, it->first, Colors::GREEN,
-		    Point(leftBottomCorner.x + 50, leftBottomCorner.y - texts.size() * 20 - 80 + number*20));
+//*		graphics->fonts[FONT_MEDIUM]->renderTextLeft(to, it->first, Colors::GREEN,
+//*		    Point(leftBottomCorner.x + 50, leftBottomCorner.y - texts.size() * 20 - 80 + number*20));
 
 		if(SDL_GetTicks() - it->second > defaultTimeout)
 		{
@@ -4339,14 +4342,14 @@ void CArtPlace::showAll()
 	if(marked && active)
 	{
 		// Draw vertical bars.
-		for (int i = 0; i < pos.h; ++i)
+		for (size_t i = 0; i < pos.h; ++i)
 		{
 //*			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x,             pos.y + i, 240, 220, 120);
 //*			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + pos.w - 1, pos.y + i, 240, 220, 120);
 		}
 
 		// Draw horizontal bars.
-		for (int i = 0; i < pos.w; ++i)
+		for (size_t i = 0; i < pos.w; ++i)
 		{
 //*			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + i, pos.y,             240, 220, 120);
 //*			CSDL_Ext::SDL_PutPixelWithoutRefresh(to, pos.x + i, pos.y + pos.h - 1, 240, 220, 120);
@@ -5247,7 +5250,6 @@ CPuzzleWindow::CPuzzleWindow(const int3 &GrailPos, double discoveredRatio):
 		if(info.whenUncovered < GameConstants::PUZZLE_MAP_PIECES * discoveredRatio)
 		{
 			piecesToRemove.push_back(piece);
-			piece->needRefresh = true;
 			piece->recActions = piece->recActions & ~SHOWALL;
 		}
 	}
@@ -5906,7 +5908,7 @@ MoraleLuckBox::MoraleLuckBox(bool Morale, const Rect &r, bool Small):
 	small(Small)
 {
 	bonusValue = 0;
-	pos = r + pos;
+	pos.addOffs_copySize(r);
 }
 
 CArtifactHolder::CArtifactHolder()
@@ -6005,7 +6007,8 @@ void CRClickPopup::createAndPush(const std::string &txt, const CInfoWindow::TCom
 	PlayerColor player = LOCPLINT ? LOCPLINT->playerID : PlayerColor(1); //if no player, then use blue
 
 	CSimpleWindow * temp = new CInfoWindow(txt, player, comps);
-	temp->center(Point(GH.current->motion)); //center on mouse
+	auto &motion = GH.current->motion;
+	temp->center(Point(motion.x, motion.y)); //center on mouse
 	temp->fitToScreen(10);
 	CRClickPopupInt *rcpi = new CRClickPopupInt(temp,true);
 	GH.pushInt(rcpi);
@@ -6078,7 +6081,7 @@ CIntObject * CRClickPopup::createInfoWin(Point position, const CGObjectInstance
 	}
 }
 
-void CRClickPopup::createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment /*= BOTTOMRIGHT*/)
+void CRClickPopup::createAndPush(const CGObjectInstance *obj, Point p, EAlignment alignment /*= BOTTOMRIGHT*/)
 {
 	CIntObject *iWin = createInfoWin(p, obj); //try get custom infowindow for this obj
 	if(iWin)

+ 3 - 3
client/GUIClasses.h

@@ -135,7 +135,7 @@ public:
 	static CIntObject* createInfoWin(Point position, const CGObjectInstance * specific);
 	static void createAndPush(const std::string &txt, const CInfoWindow::TCompsInfo &comps = CInfoWindow::TCompsInfo());
 	static void createAndPush(const std::string &txt, CComponent * component);
-	static void createAndPush(const CGObjectInstance *obj, const Point &p, EAlignment alignment = BOTTOMRIGHT);
+	static void createAndPush(const CGObjectInstance *obj, Point p, EAlignment alignment = BOTTOMRIGHT);
 };
 
 /// popup displayed on R-click
@@ -811,7 +811,7 @@ public:
 
 	void recruitb();
 	void thievesguildb();
-	void show(SDL_Surface * to);
+	void show();
 };
 
 class CInGameConsole : public CIntObject
@@ -825,7 +825,7 @@ private:
 	int maxDisplayedTexts; //hiw many texts can be displayed simultaneously
 public:
 	std::string enteredText;
-	void show(SDL_Surface * to);
+	void show();
 	void print(const std::string &txt);
 	void keyPressed (const SDL_KeyboardEvent & key); //call-in
 

+ 43 - 0
client/Gfx/Basic.cpp

@@ -0,0 +1,43 @@
+#include "StdInc.h"
+#include "Basic.h"
+
+namespace Gfx
+{
+
+void Rect::addOffs_copySize(const Rect & r)
+{
+	x += r.x;
+	y += r.y;
+	w = r.w;
+	h = r.h;
+}
+
+
+Rect Rect::operator&(const Rect &p) const //rect intersection
+{
+	bool intersect = true;
+
+	if (
+			leftX() > p.rightX() //rect p is on the left hand side of this
+		||	rightX() < p.leftX() //rect p is on the right hand side of this
+		||	topY() > p.bottomY() //rect p is above *this
+		||	bottomY() < p.topY() //rect p is below *this
+		)
+	{
+		return Rect();
+	}
+	else
+	{
+		Rect ret;
+		ret.x = std::max(this->x, p.x);
+		ret.y = std::max(this->y, p.y);
+		Point bR; //bottomRight point of returned rect
+		bR.x = std::min(this->w+this->x, p.w+p.x);
+		bR.y = std::min(this->h+this->y, p.h+p.y);
+		ret.w = bR.x - ret.x;
+		ret.h = bR.y - ret.y;
+		return ret;
+	}
+}
+
+}

+ 60 - 7
client/Gfx/Basic.h

@@ -8,17 +8,70 @@ struct Point
 	si32 x;
 	si32 y;
 
-	inline Point() {};
-	inline Point(si32 _x, si32 _y) : x(_x), y(_y) {};
+	Point() {};
+	Point(si32 _x, si32 _y) : x(_x), y(_y) {};
+
+	bool operator==(const Point &p) const
+	{
+		return (x == p.x) && (y == p.y);
+	}
+	bool operator!=(const Point &p) const
+	{
+		return !(*this == p);
+	}
+	Point& operator+=(const Point &p)
+	{
+		x += p.x;
+		y += p.y;
+		return *this;
+	}
+	Point& operator-=(const Point &p)
+	{
+		x -= p.x;
+		y -= p.y;
+		return *this;
+	}
 };
 
-struct Rect
+struct Rect : Point
 {
-	Point lt;
-	Point rb;
+	ui32 w;
+	ui32 h;
+
+	Rect() : w(0), h(0) {};
+	Rect(const Point & lt) : Point(lt), w(0), h(0) {};
+	Rect(const Point & lt, const Point & sz) : Point(lt), w(sz.x), h(sz.y) {};
+	Rect(si32 _x, si32 _y, ui32 _w, ui32 _h) : Point(_x, _y), w(_w), h(_h) {};
+
+	Rect& operator=(const Point &p)
+	{
+		x = p.x;
+		y = p.y;
+		return *this;
+	}
+
+	si32 leftX()	const { return x;     };
+	si32 centerX()	const { return x+w/2; };
+	si32 rightX()	const { return x+w;   };
+	si32 topY() 	const { return y;     };
+	si32 centerY()	const { return y+h/2; }
+	si32 bottomY()	const { return y+h;   };
+
+	//top left corner of this rect
+	Point topLeft() const {	return *this; }
+
+	//top right corner of this rect
+	Point topRight() const { return Point(x+w, y); }
+
+	//bottom left corner of this rect
+	Point bottomLeft() const { return Point(x, y+h); }
+
+	//bottom right corner of this rect
+	Point bottomRight() const { return Point(x+w, y+h); }
+
+	void addOffs_copySize(const Rect &p);
 
-	inline ui32 width() { return rb.x - lt.x; };
-	inline ui32 height() { return rb.y - lt.y; };
+	Rect Rect::operator&(const Rect &p) const; //rect intersection
 };
 
 /* Color transform matrix for: grayscale, clone, bloodlust, etc */

+ 2 - 2
client/Gfx/Images.cpp

@@ -201,8 +201,8 @@ void CBitmap32::putAt(Point p, TransformFlags flags, float scale)
 void CBitmap32::putAt(Point p, TransformFlags flags, Rect clipRect)
 {
 	QuadInstance qi(p);
-	qi.setOffset(flags, clipRect.lt.x, clipRect.lt.y);
-	qi.transform(flags, clipRect.rb.x - p.x, clipRect.rb.y - p.y, clipRect.width(), clipRect.height());
+	qi.setOffset(flags, clipRect.x, clipRect.y);
+//	qi.transform(flags, clipRect.rb.x - p.x, clipRect.rb.y - p.y, clipRect.width(), clipRect.height());
 
 	GL2D::useNoShader();
 	bindTexture();

+ 0 - 2
client/Graphics.h

@@ -1,9 +1,7 @@
 #pragma once
 
-
 #include "UIFramework/Fonts.h"
 #include "../lib/GameConstants.h"
-#include "UIFramework/Geometries.h"
 
 /*
  * Graphics.h, part of VCMI engine

+ 3 - 3
client/UIFramework/CGuiHandler.cpp

@@ -229,7 +229,7 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
 		if(sEvent->button.button == SDL_BUTTON_LEFT)
 		{
 
-			if(lastClick == sEvent->motion  &&  (SDL_GetTicks() - lastClickTime) < 300)
+			if(lastClick.x == sEvent->motion.x  &&  lastClick.y == sEvent->motion.y  &&  (SDL_GetTicks() - lastClickTime) < 300)
 			{
 				std::list<CIntObject*> hlp = doubleClickInterested;
 				for(std::list<CIntObject*>::iterator i=hlp.begin(); i != hlp.end() && current; i++)
@@ -243,7 +243,7 @@ void CGuiHandler::handleEvent(SDL_Event *sEvent)
 
 			}
 
-			lastClick = sEvent->motion;
+			lastClick = Point(sEvent->motion.x, sEvent->motion.y);
 			lastClickTime = SDL_GetTicks();
 
 			std::list<CIntObject*> hlp = lclickable;
@@ -541,7 +541,7 @@ void CFramerateManager::framerateDelay()
 	}
 	currentTicks = SDL_GetTicks();
 
-	fps = ceil(1000.0 / timeElapsed);
+	fps = (int)ceil(1000.0 / timeElapsed);
 
 	//recalculate timeElapsed for external calls via getElapsed()
 	timeElapsed = currentTicks - lastticks;

+ 3 - 2
client/UIFramework/CGuiHandler.h

@@ -1,7 +1,8 @@
 #pragma once
 
+#include <SDL_events.h>
 #include "../../lib/CStopWatch.h"
-#include "Geometries.h"
+#include "../Gfx/Basic.h"
 
 class CFramerateManager;
 class CGStatusBar;
@@ -70,7 +71,7 @@ public:
 	SDL_Event * current; //current event - can be set to NULL to stop handling event
 	IUpdateable *curInt;
 
-	Point lastClick;
+	Gfx::Point lastClick;
 	unsigned lastClickTime;
 	bool terminate;
 

+ 14 - 18
client/UIFramework/CIntObject.cpp

@@ -5,23 +5,19 @@
 #include "SDL_Extensions.h"
 #include "../CMessage.h"
 
-CIntObject::CIntObject(int used_, Point pos_):
+CIntObject::CIntObject(int used_, Point offset) :
+	used(used_),
 	parent_m(nullptr),
 	active_m(0),
 	parent(parent_m),
-	active(active_m)
+	active(active_m),
+	pos(offset)
 {
 	pressedL = pressedR = hovered = captureAllKeys = strongInterest = false;
 	toNextTick = timerDelay = 0;
-	used = used_;
 
 	recActions = defActions = GH.defActionsDef;
 
-	pos.x = pos_.x;
-	pos.y = pos_.y;
-	pos.w = 0;
-	pos.h = 0;
-
 	if(GH.captureChildren)
 		GH.createdObj.front()->addChild(this, true);
 }
@@ -80,7 +76,7 @@ void CIntObject::activate()
 	activate(used);
 
 	if(defActions & ACTIVATE)
-		for(size_t i = 0; i < children.size(); i++)
+		for(size_t i = 0; i < children.size(); ++i)
 			if(children[i]->recActions & ACTIVATE)
 				children[i]->activate();
 }
@@ -139,9 +135,9 @@ void CIntObject::printAtMiddleLoc( const std::string & text, int x, int y, EFont
 	printAtMiddleLoc(text, Point(x,y), font, kolor, dst);
 }
 
-void CIntObject::printAtMiddleLoc(const std::string & text, const Point &p, EFonts font, SDL_Color kolor, SDL_Surface * dst)
+void CIntObject::printAtMiddleLoc(const std::string & text, Point p, EFonts font, SDL_Color kolor, SDL_Surface * dst)
 {
-	graphics->fonts[font]->renderTextCenter(dst, text, kolor, pos.topLeft() + p);
+	graphics->fonts[font]->renderTextCenter(dst, text, kolor, p += pos);
 }
 
 void CIntObject::blitAtLoc( SDL_Surface * src, int x, int y, SDL_Surface * dst )
@@ -194,12 +190,12 @@ void CIntObject::enable()
 	recActions = 255;
 }
 
-bool CIntObject::isItInLoc( const SDL_Rect &rect, int x, int y )
+bool CIntObject::isItInLoc(const Rect &rect, int x, int y)
 {
 	return isItIn(&rect, x - pos.x, y - pos.y);
 }
 
-bool CIntObject::isItInLoc( const SDL_Rect &rect, const Point &p )
+bool CIntObject::isItInLoc(const Rect &rect, Point p)
 {
 	return isItIn(&rect, p.x - pos.x, p.y - pos.y);
 }
@@ -215,16 +211,16 @@ void CIntObject::fitToScreen(int borderWidth, bool propagate)
 		moveTo(newPos, propagate);
 }
 
-void CIntObject::moveBy( const Point &p, bool propagate /*= true*/ )
+void CIntObject::moveBy(Point p, bool propagate /*= true*/ )
 {
 	pos.x += p.x;
 	pos.y += p.y;
 	if(propagate)
-		for(size_t i = 0; i < children.size(); i++)
+		for(size_t i = 0; i < children.size(); ++i)
 			children[i]->moveBy(p, propagate);
 }
 
-void CIntObject::moveTo( const Point &p, bool propagate /*= true*/ )
+void CIntObject::moveTo(Point p, bool propagate /*= true*/ )
 {
 	moveBy(Point(p.x - pos.x, p.y - pos.y), propagate);
 }
@@ -267,7 +263,7 @@ void CIntObject::removeChild(CIntObject *child, bool adjustPosition /*= false*/)
 
 void CIntObject::drawBorderLoc(SDL_Surface * sur, const Rect &r, const int3 &color)
 {
-	CSDL_Ext::drawBorder(sur, r + pos, color);
+//*	CSDL_Ext::drawBorder(sur, r + pos, color);
 }
 
 void CIntObject::redraw()
@@ -299,7 +295,7 @@ const Rect & CIntObject::center( bool propagate )
 	return center(pos, propagate);
 }
 
-const Rect & CIntObject::center(const Point &p, bool propagate /*= true*/)
+const Rect & CIntObject::center(Point p, bool propagate /*= true*/)
 {
 	moveBy(Point(p.x - pos.w/2 - pos.x, 
 		p.y - pos.h/2 - pos.y), 

+ 13 - 11
client/UIFramework/CIntObject.h

@@ -1,7 +1,8 @@
 #pragma once
 
 #include <SDL_events.h>
-#include "Geometries.h"
+#include "../../lib/int3.h"
+#include "../Gfx/Basic.h"
 #include "../Graphics.h"
 
 struct SDL_Surface;
@@ -19,6 +20,8 @@ class CGuiHandler;
  */
 
 using boost::logic::tribool;
+using Gfx::Point;
+using Gfx::Rect;
 
 // Defines a activate/deactive method
 class IActivatable
@@ -64,7 +67,6 @@ public:
 // Base UI element
 class CIntObject : public IShowActivatable //interface object
 {
-
 	ui16 used;//change via addUsed() or delUsed
 
 	//time handling
@@ -100,11 +102,12 @@ public:
 
 	/// read-only parent access. May not be a "clean" solution but allows some compatibility
 	CIntObject * const & parent;
+	const ui16 & active;
 
 	/// position of object on the screen. Please do not modify this anywhere but in constructor - use moveBy\moveTo instead
-	/*const*/ Rect pos;
+	Rect pos;
 
-	CIntObject(int used=0, Point offset=Point());
+	CIntObject(int used_ = 0, Point offset = Point(0, 0));
 	virtual ~CIntObject(); //d-tor
 
 	//l-clicks handling
@@ -139,7 +142,6 @@ public:
 	virtual void onDoubleClick(){}
 
 	enum {LCLICK=1, RCLICK=2, HOVER=4, MOVE=8, KEYBOARD=16, TIME=32, GENERAL=64, WHEEL=128, DOUBLECLICK=256, ALL=0xffff};
-	const ui16 & active;
 	void addUsedEvents(ui16 newActions);
 	void removeUsedEvents(ui16 newActions);
 
@@ -164,14 +166,14 @@ public:
 
 	enum EAlignment {TOPLEFT, CENTER, BOTTOMRIGHT};
 
-	bool isItInLoc(const SDL_Rect &rect, int x, int y);
-	bool isItInLoc(const SDL_Rect &rect, const Point &p);
+	bool isItInLoc(const Rect &rect, int x, int y);
+	bool isItInLoc(const Rect &rect, Point p);
 	const Rect & center(const Rect &r, bool propagate = true); //sets pos so that r will be in the center of screen, assigns sizes of r to pos, returns new position
-	const Rect & center(const Point &p, bool propagate = true);  //moves object so that point p will be in its center
+	const Rect & center(Point p, bool propagate = true);  //moves object so that point p will be in its center
 	const Rect & center(bool propagate = true); //centers when pos.w and pos.h are set, returns new position
 	void fitToScreen(int borderWidth, bool propagate = true); //moves window to fit into screen
-	void moveBy(const Point &p, bool propagate = true);
-	void moveTo(const Point &p, bool propagate = true);//move this to new position, coordinates are absolute (0,0 is topleft screen corner)
+	void moveBy(Point p, bool propagate = true);
+	void moveTo(Point p, bool propagate = true);//move this to new position, coordinates are absolute (0,0 is topleft screen corner)
 
 	void addChild(CIntObject *child, bool adjustPosition = false);
 	void removeChild(CIntObject *child, bool adjustPosition = false);
@@ -187,7 +189,7 @@ public:
 	void printAtLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst);
 	void printToLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst);
 	void printAtMiddleLoc(const std::string & text, int x, int y, EFonts font, SDL_Color color, SDL_Surface * dst);
-	void printAtMiddleLoc(const std::string & text, const Point &p, EFonts font, SDL_Color color, SDL_Surface * dst);
+	void printAtMiddleLoc(const std::string & text, Point p, EFonts font, SDL_Color color, SDL_Surface * dst);
 	void printAtMiddleWBLoc(const std::string & text, int x, int y, EFonts font, int charsPerLine, SDL_Color color, SDL_Surface * dst);
 
 	//image blitting. If possible use CPicture or CAnimImage instead

+ 51 - 54
client/UIFramework/CIntObjectClasses.cpp

@@ -25,8 +25,7 @@
 CPicture::CPicture(Gfx::PImage BG, int x, int y, bool Free )
 {
 	init();
-	bg = BG;
-	freeSurf = Free;
+	image = BG;
 	pos.x += x;
 	pos.y += y;
 	pos.w = BG->getWidth();
@@ -36,14 +35,13 @@ CPicture::CPicture(Gfx::PImage BG, int x, int y, bool Free )
 CPicture::CPicture( const std::string &bmpname, int x, int y )
 {
 	init();
-	bg = Gfx::CManager::getImage(bmpname);
-	freeSurf = true;;
+	image = Gfx::CManager::getImage(bmpname);
 	pos.x += x;
 	pos.y += y;
-	if(bg)
+	if(image)
 	{
-		pos.w = bg->getWidth();
-		pos.h = bg->getHeight();
+		pos.w = image->getWidth();
+		pos.h = image->getHeight();
 	}
 	else
 	{
@@ -65,30 +63,14 @@ CPicture::CPicture(const Rect &r, ui32 color, bool screenFormat /*= false*/)
 
 CPicture::CPicture(Gfx::PImage BG, const Rect &SrcRect, int x /*= 0*/, int y /*= 0*/, bool free /*= false*/)
 {
-	needRefresh = false;
 	srcRect = new Rect(SrcRect);
 	pos.x += x;
 	pos.y += y;
 	pos.w = srcRect->w;
 	pos.h = srcRect->h;
-	bg = BG;
-	freeSurf = free;
+	image = BG;
 }
 
-void CPicture::setSurface(SDL_Surface *to)
-{
-//*	bg = to;
-	if (srcRect)
-	{
-		pos.w = srcRect->w;
-		pos.h = srcRect->h;
-	}
-	else
-	{
-		pos.w = bg->getWidth();
-		pos.h = bg->getHeight();
-	}
-}
 
 CPicture::~CPicture()
 {
@@ -97,18 +79,17 @@ CPicture::~CPicture()
 
 void CPicture::init()
 {
-	needRefresh = false;
 	srcRect = NULL;
 }
 
 void CPicture::show()
 {
-	if (bg) bg->putAt(Gfx::Point(pos.x, pos.y));
+	if (image) image->putAt(pos);
 }
 
 void CPicture::showAll()
 {
-	if (bg) bg->putAt(Gfx::Point(pos.x, pos.y));
+	if (image) image->putAt(pos);
 /*
 	if(bg)
 	{
@@ -163,19 +144,16 @@ void CPicture::createSimpleRect(const Rect &r, bool screenFormat, ui32 color)
 		bg = SDL_CreateRGBSurface(SDL_SWSURFACE, r.w, r.h, 8, 0, 0, 0, 0);
 
 	SDL_FillRect(bg, NULL, color); */
-	freeSurf = true;
 }
 
 void CPicture::colorizeAndConvert(PlayerColor player)
 {
-	assert(bg);
 	colorize(player);
 	convertToScreenBPP();
 }
 
 void CPicture::colorize(PlayerColor player)
 {
-	assert(bg);
 //*	assert(bg->format->BitsPerPixel == 8);
 //*	graphics->blueToPlayersAdv(bg, player);
 }
@@ -208,8 +186,8 @@ CButton::CButton() :
 }
 
 
-CButton::CButton(const CFunctionList<void()> & flist, Gfx::Point position, const std::string & animName, size_t animOffs/*=0*/, size_t imagesNum/*=4*/,
-				 const PairOfStrings * helpStr, ui16 events/*=LCLICK|RCLICK|HOVER|KEYBOARD*/, int key/*=0*/) :
+CButton::CButton(const CFunctionList<void()> & flist, Point position, const std::string & animName, size_t animOffs/*=0*/, size_t imagesNum/*=4*/,
+				 const PairOfStrings * helpStr, int key/*=0*/) :
 	state(NORMAL),
 	images(Gfx::CManager::getAnimation(animName)),
 	callback(flist),
@@ -218,10 +196,20 @@ CButton::CButton(const CFunctionList<void()> & flist, Gfx::Point position, const
 	pos.x = position.x;
 	pos.y = position.y;
 
+	ui16 events = LCLICK;
+
 	if (helpStr != nullptr)
 	{
-		helpBox = helpStr->first;
-		status = helpStr->second;
+		if (helpStr->first.size() > 0)
+		{
+			helpBox = helpStr->first;
+			events |= RCLICK;
+		}
+		if (helpStr->second.size() > 0)
+		{
+			status = helpStr->second;
+			events |= HOVER;
+		}
 	}
 
 	if (images)
@@ -229,27 +217,32 @@ CButton::CButton(const CFunctionList<void()> & flist, Gfx::Point position, const
 		pos.w = images->getWidth();
 		pos.h = images->getHeight();
 
-		size_t i=0;
+		size_t i = 0;
 		for (; i<imagesNum; ++i)
 		{
-			state2image[i] = images->getFrame(i + animOffs);
-			if (state2image[i] == nullptr)
+			if ((state2image[i] = images->getFrame(i + animOffs)) == nullptr)
 			{
 				tlog2 << "CButton warning: image " << animName << " : " << animOffs+i << " is missing\n";
-				state2image[i] = state2image[0]; //TODO set dummy image
+				state2image[i] = state2image[NORMAL]; //TODO set dummy image
 			}
 		}
-		for (; i<4; ++i)
+		for (; i<4; ++i) state2image[i] = state2image[NORMAL];
+
+		if (state2image[HIGHLIGHTED] != state2image[NORMAL])
 		{
-			state2image[i] = state2image[0];
+			events |= HOVER;
 		}
 	}
 	else {
 		tlog1 << "CButton error: animation file '" << animName << "' is not loaded\n";
 	}
 
+	if (key != SDLK_UNKNOWN)
+	{
+		assignedKeys.insert(key);
+		events |= KEYBOARD;
+	}
 	addUsedEvents(events);
-	if (key != SDLK_UNKNOWN) assignedKeys.insert(key);
 }
 
 
@@ -327,7 +320,7 @@ void CButton::block(bool on)
 
 void CButton::showAll()
 {
-	state2image[state]->putAt(Gfx::Point(pos.x, pos.y));
+	state2image[state]->putAt(pos);
 }
 
 CAdventureMapButton::CAdventureMapButton()
@@ -682,7 +675,7 @@ void CSlider::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 	double v = 0;
 	if(horizontal)
 	{
-		if(	std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2+40  ||  std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2  )
+		if(	std::abs(sEvent.y - pos.centerY()) > pos.h/2+40  ||  std::abs(sEvent.x - pos.centerX()) > pos.w/2  )
 			return;
 		v = sEvent.x - pos.x - 24;
 		v *= positions;
@@ -690,7 +683,7 @@ void CSlider::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 	}
 	else
 	{
-		if(std::abs(sEvent.x-(pos.x+pos.w/2)) > pos.w/2+40  ||  std::abs(sEvent.y-(pos.y+pos.h/2)) > pos.h/2  )
+		if(std::abs(sEvent.x - pos.centerX()) > pos.w/2+40  ||  std::abs(sEvent.y - pos.centerY()) > pos.h/2  )
 			return;
 		v = sEvent.y - pos.y - 24;
 		v *= positions;
@@ -735,7 +728,7 @@ void CSlider::moveTo(int to)
 		{
 			double part = static_cast<double>(to) / positions;
 			part*=(pos.w-48);
-			int newPos = part + pos.x + 16 - slider->pos.x;
+			int newPos = (int)part + pos.x + 16 - slider->pos.x;
 			slider->moveBy(Point(newPos, 0));
 		}
 		else
@@ -747,7 +740,7 @@ void CSlider::moveTo(int to)
 		{
 			double part = static_cast<double>(to) / positions;
 			part*=(pos.h-48);
-			int newPos = part + pos.y + 16 - slider->pos.y;
+			int newPos = (int)part + pos.y + 16 - slider->pos.y;
 			slider->moveBy(Point(0, newPos));
 		}
 		else
@@ -1206,7 +1199,7 @@ LRClickableAreaWText::LRClickableAreaWText()
 LRClickableAreaWText::LRClickableAreaWText(const Rect &Pos, const std::string &HoverText /*= ""*/, const std::string &ClickText /*= ""*/)
 {
 	init();
-	pos = Pos + pos;
+	pos.addOffs_copySize(Pos);
 	hoverText = HoverText;
 	text = ClickText;
 }
@@ -1340,8 +1333,10 @@ void CBoundedLabel::showAll()
 
 //	int dy = f->getLineHeight(); //line height
 	int base_y = pos.y;
-	if(alignment == CENTER)
-		base_y += std::max((pos.h - maxH)/2,0);
+	if (alignment == CENTER && (int)(pos.h - maxH) > 0)
+	{
+		base_y += (pos.h - maxH) / 2;
+	}
 
 	for (int i = 0; i < lineCapacity; i++)
 	{
@@ -1430,13 +1425,15 @@ void CTextBox::showAll()
 //	int dy = f->getLineHeight(); //line height
 	int base_y = pos.y;
 
-	if (alignment == CENTER)
-		base_y += std::max((pos.h - maxH)/2,0);
+	if (alignment == CENTER && (int)(pos.h - maxH) > 0)
+	{
+		base_y += (pos.h - maxH) / 2;
+	}
 
-	int howManyLinesToPrint = slider ? slider->capacity : lines.size();
+	size_t howManyLinesToPrint = slider ? slider->capacity : lines.size();
 	int firstLineToPrint = slider ? slider->value : 0;
 
-	for (int i = 0; i < howManyLinesToPrint; i++)
+	for (size_t i = 0; i < howManyLinesToPrint; ++i)
 	{
 		const std::string &line = lines[i + firstLineToPrint];
 		if(!line.size()) continue;
@@ -1580,7 +1577,7 @@ CTextInput::CTextInput(const Rect &Pos, SDL_Surface *srf)
 	captureAllKeys = true;
 	OBJ_CONSTRUCTION;
 	bg = new CPicture(Pos, 0, true);
-//	Rect hlp = Pos;
+//*	Rect hlp = Pos;
 /*	if(srf)
 		CSDL_Ext::blitSurface(srf, &hlp, *bg, NULL);
 	else

+ 5 - 10
client/UIFramework/CIntObjectClasses.h

@@ -7,7 +7,6 @@
 #include "../Gfx/Manager.h"
 
 struct SDL_Surface;
-struct Rect;
 class CAnimImage;
 class CLabel;
 class CAnimation;
@@ -36,15 +35,12 @@ public:
 // Image class
 class CPicture : public CIntObject
 {
-	void setSurface(SDL_Surface *to);
-	Gfx::PImage bg;
+	Gfx::PImage image;
 
 public: 
 	Rect * srcRect; //if NULL then whole surface will be used
-	bool freeSurf; //whether surface will be freed upon CPicture destruction
-	bool needRefresh;//Surface needs to be displayed each frame
 
-	inline Gfx::PImage getImage() { return bg; };
+	inline Gfx::PImage getImage() { return image; };
 
 	CPicture(const Rect & r, const SDL_Color & color, bool screenFormat = false); //rect filled with given color
 	CPicture(const Rect & r, ui32 color, bool screenFormat = false); //rect filled with given color
@@ -107,12 +103,11 @@ public:
 	CLabel * text; //text overlay
 
 	CButton(	const CFunctionList<void()> & flist,
-				Gfx::Point position,
+				Point position,
 				const std::string & animName,
 				size_t animOffs = 0,
 				size_t imagesNum = 4,
 				const PairOfStrings * helpStr = nullptr,
-				ui16 events = LCLICK | RCLICK | HOVER | KEYBOARD,
 				int key = SDLK_UNKNOWN
 			);
 	virtual ~CButton(); //d-tor
@@ -364,8 +359,8 @@ class CBoundedLabel : public CLabel
 {
 public:
 
-	int maxW; //longest line of text in px
-	int maxH; //total height needed to print all lines
+	ui32 maxW; //longest line of text in px
+	ui32 maxH; //total height needed to print all lines
 
 	std::vector<std::string> lines;
 

+ 21 - 21
client/UIFramework/Fonts.cpp

@@ -19,26 +19,26 @@
  */
 
 
-void IFont::renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
+void IFont::renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const
 {
 	renderText(surface, data, color, pos);
 }
 
-void IFont::renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
+void IFont::renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const
 {
-	Point size(getStringWidth(data), getLineHeight());
-	renderText(surface, data, color, pos - size);
+	Gfx::Point size(getStringWidth(data), getLineHeight());
+	renderText(surface, data, color, pos -= size);
 }
 
-void IFont::renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
+void IFont::renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const
 {
-	Point size(getStringWidth(data), getLineHeight());
-	renderText(surface, data, color, pos - size / 2);
+	Gfx::Point size(getStringWidth(data), getLineHeight());
+//*	renderText(surface, data, color, pos - size / 2);
 }
 
-void IFont::renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
+void IFont::renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, Gfx::Point pos) const
 {
-	Point currPos = pos;
+	Gfx::Point currPos = pos;
 
 	BOOST_FOREACH(const std::string & line, data)
 	{
@@ -47,9 +47,9 @@ void IFont::renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::st
 	}
 }
 
-void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
+void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, Gfx::Point pos) const
 {
-	Point currPos = pos;
+	Gfx::Point currPos = pos;
 	currPos.y -= data.size() * getLineHeight();
 
 	BOOST_FOREACH(const std::string & line, data)
@@ -59,9 +59,9 @@ void IFont::renderTextLinesRight(SDL_Surface * surface, const std::vector<std::s
 	}
 }
 
-void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const
+void IFont::renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, Gfx::Point pos) const
 {
-	Point currPos = pos;
+	Gfx::Point currPos = pos;
 	currPos.y -= data.size() * getLineHeight()/2;
 
 	BOOST_FOREACH(const std::string & line, data)
@@ -124,8 +124,8 @@ size_t CBitmapFont::getStringWidth(const std::string & data) const
 
 void CBitmapFont::renderCharacter(SDL_Surface * surface, const Char & character, const SDL_Color & color, int &posX, int &posY) const
 {
-	Rect clipRect;
-	SDL_GetClipRect(surface, &clipRect);
+	Gfx::Rect clipRect;
+//*	SDL_GetClipRect(surface, &clipRect);
 
 	posX += character.leftOffset;
 
@@ -172,7 +172,7 @@ void CBitmapFont::renderCharacter(SDL_Surface * surface, const Char & character,
 	posX += character.rightOffset;
 }
 
-void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
+void CBitmapFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const
 {
 	if (data.empty())
 		return;
@@ -254,12 +254,12 @@ size_t CTrueTypeFont::getStringWidth(const std::string & data) const
 	return width;
 }
 
-void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const
+void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const
 {
 	if (color.r != 0 && color.g != 0 && color.b != 0) // not black - add shadow
 	{
 		SDL_Color black = { 0, 0, 0, SDL_ALPHA_OPAQUE};
-		renderText(surface, data, black, Point(pos.x + 1, pos.y + 1));
+		renderText(surface, data, black, Gfx::Point(pos.x + 1, pos.y + 1));
 	}
 
 	if (!data.empty())
@@ -272,8 +272,8 @@ void CTrueTypeFont::renderText(SDL_Surface * surface, const std::string & data,
 
 		assert(rendered);
 
-		Rect rect(pos.x, pos.y, rendered->w, rendered->h);
-		SDL_BlitSurface(rendered, NULL, surface, &rect);
-		SDL_FreeSurface(rendered);
+		Gfx::Rect rect(pos.x, pos.y, rendered->w, rendered->h);
+//*		SDL_BlitSurface(rendered, NULL, surface, &rect);
+//*		SDL_FreeSurface(rendered);
 	}
 }

+ 11 - 10
client/UIFramework/Fonts.h

@@ -10,9 +10,10 @@
  *
  */
 
+#include "../Gfx/Basic.h"
+
 class JsonNode;
 
-struct Point;
 struct SDL_Surface;
 struct SDL_Color;
 
@@ -22,7 +23,7 @@ class IFont
 {
 protected:
 	/// Internal function to render font, see renderTextLeft
-	virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const = 0;
+	virtual void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const = 0;
 
 public:
 	virtual ~IFont()
@@ -42,18 +43,18 @@ public:
 	 * @param pos - position of rendered font
 	 */
 	/// pos = topleft corner of the text
-	void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
+	void renderTextLeft(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const;
 	/// pos = center of the text
-	void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
+	void renderTextRight(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const;
 	/// pos = bottomright corner of the text
-	void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
+	void renderTextCenter(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const;
 
 	/// pos = topleft corner of the text
-	void renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
+	void renderTextLinesLeft(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, Gfx::Point pos) const;
 	/// pos = center of the text
-	void renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
+	void renderTextLinesRight(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, Gfx::Point pos) const;
 	/// pos = bottomright corner of the text
-	void renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, const Point & pos) const;
+	void renderTextLinesCenter(SDL_Surface * surface, const std::vector<std::string> & data, const SDL_Color & color, Gfx::Point pos) const;
 };
 
 class CBitmapFont : public IFont
@@ -77,7 +78,7 @@ class CBitmapFont : public IFont
 
 	void renderCharacter(SDL_Surface * surface, const Char & character, const SDL_Color & color, int &posX, int &posY) const;
 
-	void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
+	void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const;
 public:
 	CBitmapFont(const std::string & filename);
 
@@ -97,7 +98,7 @@ class CTrueTypeFont : public IFont
 	TTF_Font * loadFont(const JsonNode & config);
 	int getFontStyle(const JsonNode & config);
 
-	void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, const Point & pos) const;
+	void renderText(SDL_Surface * surface, const std::string & data, const SDL_Color & color, Gfx::Point pos) const;
 public:
 	CTrueTypeFont(const JsonNode & fontConfig);
 

+ 4 - 1
client/UIFramework/Geometries.cpp

@@ -1,6 +1,7 @@
 #include "StdInc.h"
 #include "Geometries.h"
 
+#if 0
 extern SDL_Surface * screen;
 
 Rect Rect::createCentered( int w, int h )
@@ -16,4 +17,6 @@ Rect Rect::around(const Rect &r, int width /*= 1*/) /*creates rect around anothe
 Rect Rect::centerIn(const Rect &r)
 {
 	return Rect(r.x + (r.w - w) / 2, r.y + (r.h - h) / 2, w, h);
-}
+}
+
+#endif

+ 5 - 1
client/UIFramework/Geometries.h

@@ -1,5 +1,7 @@
 #pragma once
 
+#if 0
+
 #include <SDL_video.h>
 #include <SDL_events.h>
 #include "../../lib/int3.h"
@@ -265,4 +267,6 @@ struct Rect : public SDL_Rect
 		ret.h = y2 -ret.y;
 		return ret;
 	}
-};
+};
+
+#endif

+ 6 - 6
client/UIFramework/SDL_Extensions.cpp

@@ -44,7 +44,7 @@ SDL_Surface * CSDL_Ext::createSurfaceWithBpp(int width, int height)
 	return SDL_CreateRGBSurface( SDL_SWSURFACE, width, height, bpp * 8, rMask, gMask, bMask, aMask);
 }
 
-bool isItIn(const SDL_Rect * rect, int x, int y)
+bool isItIn(const Gfx::Rect * rect, int x, int y)
 {
 	return (x>rect->x && x<rect->x+rect->w) && (y>rect->y && y<rect->y+rect->h);
 }
@@ -557,7 +557,7 @@ void CSDL_Ext::drawBorder( SDL_Surface * sur, const SDL_Rect &r, const int3 &col
 	drawBorder(sur, r.x, r.y, r.w, r.h, color);
 }
 
-void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Rect &r, const int3 &color)
+void CSDL_Ext::drawDashedBorder(SDL_Surface * sur, const Gfx::Rect &r, const int3 &color)
 {
 	const int y1 = r.y, y2 = r.y + r.h-1;
 	for (int i=0; i<r.w; i++)
@@ -946,7 +946,7 @@ void CSDL_Ext::blitSurface( SDL_Surface * src, SDL_Rect * srcRect, SDL_Surface *
 		}
 		else
 		{
-			betterDst = Rect(0, 0, dst->w, dst->h);
+//*			betterDst = SDL_Rect(0, 0, dst->w, dst->h);
 		}
 
 		SDL_BlitSurface(src, srcRect, dst, &betterDst);
@@ -962,7 +962,7 @@ void CSDL_Ext::fillRect( SDL_Surface *dst, SDL_Rect *dstrect, Uint32 color )
 	}
 	else
 	{
-		newRect = Rect(0, 0, dst->w, dst->h);
+//*		newRect = SDL_Rect(0, 0, dst->w, dst->h);
 	}
 	SDL_FillRect(dst, &newRect, color);
 }
@@ -981,8 +981,8 @@ void CSDL_Ext::fillTexture(SDL_Surface *dst, SDL_Surface * src)
 		{
 			int xLeft = std::min<int>(srcRect.w, dstRect.x + dstRect.w - x);
 			int yLeft = std::min<int>(srcRect.h, dstRect.y + dstRect.h - y);
-			Rect currentDest(x, y, xLeft, yLeft);
-			SDL_BlitSurface(src, &srcRect, dst, &currentDest);
+//*			Rect currentDest(x, y, xLeft, yLeft);
+//*			SDL_BlitSurface(src, &srcRect, dst, &currentDest);
 		}
 	}
 }

+ 8 - 11
client/UIFramework/SDL_Extensions.h

@@ -4,7 +4,6 @@
 #include <SDL_ttf.h>
 #include "../../lib/int3.h"
 #include "../Graphics.h"
-#include "Geometries.h"
 
 /*
  * SDL_Extensions.h, part of VCMI engine
@@ -29,13 +28,11 @@
 #define SDL_GetKeyState SDL_GetKeyboardState
 #endif
 
-struct Rect;
-
 extern SDL_Surface * screen, *screen2, *screenBuf;
 void blitAt(SDL_Surface * src, int x, int y, SDL_Surface * dst=screen);
 void blitAt(SDL_Surface * src, const SDL_Rect & pos, SDL_Surface * dst=screen);
 void updateRect (SDL_Rect * rect, SDL_Surface * scr = screen);
-bool isItIn(const SDL_Rect * rect, int x, int y);
+bool isItIn(const Gfx::Rect * rect, int x, int y);
 
 /**
  * The colors class defines color constants of type SDL_Color.
@@ -85,9 +82,9 @@ std::string makeNumberShort(IntType number) //the output is a string containing
 typedef void (*TColorPutter)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B);
 typedef void (*TColorPutterAlpha)(Uint8 *&ptr, const Uint8 & R, const Uint8 & G, const Uint8 & B, const Uint8 & A);
 
-inline SDL_Rect genRect(const int & hh, const int & ww, const int & xx, const int & yy)
+inline Gfx::Rect genRect(const int & hh, const int & ww, const int & xx, const int & yy)
 {
-	SDL_Rect ret;
+	Gfx::Rect ret;
 	ret.h=hh;
 	ret.w=ww;
 	ret.x=xx;
@@ -116,16 +113,16 @@ namespace CSDL_Ext
 		SDL_Surface * surf;
 		SDL_Rect oldRect;
 	public:
-		CClipRectGuard(SDL_Surface * surface, const SDL_Rect & rect):
+		CClipRectGuard(SDL_Surface * surface, const Gfx::Rect & rect):
 			surf(surface)
 		{
-			SDL_GetClipRect(surf, &oldRect);
-			SDL_SetClipRect(surf, &rect);
+//*			SDL_GetClipRect(surf, &oldRect);
+//*			SDL_SetClipRect(surf, &rect);
 		}
 
 		~CClipRectGuard()
 		{
-			SDL_SetClipRect(surf, &oldRect);
+//*			SDL_SetClipRect(surf, &oldRect);
 		}
 	};
 
@@ -175,7 +172,7 @@ namespace CSDL_Ext
 	void update(SDL_Surface * what = screen); //updates whole surface (default - main screen)
 	void drawBorder(SDL_Surface * sur, int x, int y, int w, int h, const int3 &color);
 	void drawBorder(SDL_Surface * sur, const SDL_Rect &r, const int3 &color);
-	void drawDashedBorder(SDL_Surface * sur, const Rect &r, const int3 &color);
+	void drawDashedBorder(SDL_Surface * sur, const Gfx::Rect &r, const int3 &color);
 	void setPlayerColor(SDL_Surface * sur, PlayerColor player); //sets correct color of flags; -1 for neutral
 	std::string processStr(std::string str, std::vector<std::string> & tor); //replaces %s in string
 	SDL_Surface * newSurface(int w, int h, SDL_Surface * mod=screen); //creates new surface, with flags/format same as in surface given

+ 1 - 0
client/VCMI_client.vcxproj

@@ -183,6 +183,7 @@
     <ClCompile Include="CSpellWindow.cpp" />
     <ClCompile Include="CVideoHandler.cpp" />
     <ClCompile Include="Gfx\Animations.cpp" />
+    <ClCompile Include="Gfx\Basic.cpp" />
     <ClCompile Include="Gfx\CPaletteRGBA.cpp" />
     <ClCompile Include="Gfx\Images.cpp" />
     <ClCompile Include="Gfx\ImgMakers.cpp" />

+ 9 - 2
client/VCMI_client.vcxproj.filters

@@ -33,7 +33,6 @@
     <ClCompile Include="UIFramework\Geometries.cpp" />
     <ClCompile Include="UIFramework\SDL_Extensions.cpp" />
     <ClCompile Include="CQuestLog.cpp" />
-    <ClCompile Include="UIFramework\Fonts.cpp" />
     <ClCompile Include="Gfx\Animations.cpp">
       <Filter>Gfx</Filter>
     </ClCompile>
@@ -61,6 +60,12 @@
     <ClCompile Include="UIFramework\CGuiHandler.cpp">
       <Filter>UIFramework</Filter>
     </ClCompile>
+    <ClCompile Include="UIFramework\Fonts.cpp">
+      <Filter>UIFramework</Filter>
+    </ClCompile>
+    <ClCompile Include="Gfx\Basic.cpp">
+      <Filter>Gfx</Filter>
+    </ClCompile>
   </ItemGroup>
   <ItemGroup>
     <ClInclude Include="..\Global.h" />
@@ -102,7 +107,6 @@
       <Filter>Source Files</Filter>
     </ClCompile>
     <ClInclude Include="mapHandler.h" />
-    <ClInclude Include="UIFramework\Fonts.h" />
     <ClInclude Include="Gfx\Animations.h">
       <Filter>Gfx</Filter>
     </ClInclude>
@@ -133,6 +137,9 @@
     <ClInclude Include="UIFramework\CIntObjectClasses.h">
       <Filter>UIFramework</Filter>
     </ClInclude>
+    <ClInclude Include="UIFramework\Fonts.h">
+      <Filter>UIFramework</Filter>
+    </ClInclude>
   </ItemGroup>
   <ItemGroup>
     <ResourceCompile Include="VCMI_client.rc" />

+ 40 - 39
client/mapHandler.cpp

@@ -78,7 +78,7 @@ std::string nameFromType (int typ)
 
 struct OCM_HLP
 {
-	bool operator ()(const std::pair<const CGObjectInstance*, SDL_Rect> & a, const std::pair<const CGObjectInstance*, SDL_Rect> & b)
+	bool operator ()(const std::pair<const CGObjectInstance*, Gfx::Rect> & a, const std::pair<const CGObjectInstance*, Gfx::Rect> & b)
 	{
 		return (*a.first)<(*b.first);
 	}
@@ -293,12 +293,12 @@ void CMapHandler::initObjectRects()
 		{
 			for(int fy=0; fy<bitmap->h>>5; ++fy) //bitmap->h/32
 			{
-				SDL_Rect cr;
+				Gfx::Rect cr;
 				cr.w = 32;
 				cr.h = 32;
 				cr.x = fx<<5; //fx*32
 				cr.y = fy<<5; //fy*32
-				std::pair<const CGObjectInstance*,SDL_Rect> toAdd = std::make_pair(obj,cr);
+				std::pair<const CGObjectInstance*,Gfx::Rect> toAdd = std::make_pair(obj,cr);
 				
 				if(    (obj->pos.x + fx - bitmap->w/32+1)  >=  0 
 					&& (obj->pos.x + fx - bitmap->w/32+1)  <  ttiles.size() - frameW 
@@ -395,7 +395,7 @@ 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, ui8 anim, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap, bool otherHeroAnim, ui8 heroAnim, SDL_Surface * extSurf, const SDL_Rect * extRect, int moveX, int moveY, bool puzzleMode, int3 grailPosRel ) const
+void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap, bool otherHeroAnim, ui8 heroAnim, SDL_Surface * extSurf, const Gfx::Rect * extRect, int moveX, int moveY, bool puzzleMode, int3 grailPosRel ) const
 {
 	// Width and height of the portion of the map to process. Units in tiles.
 	ui32 dx = tilesW;
@@ -450,9 +450,9 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 	if(!otherHeroAnim)
 		heroAnim = anim; //the same, as it should be
 
-	SDL_Rect prevClip;
-	SDL_GetClipRect(extSurf, &prevClip);
-	SDL_SetClipRect(extSurf, extRect); //preventing blitting outside of that rect
+//*	SDL_Rect prevClip;
+//*	SDL_GetClipRect(extSurf, &prevClip);
+//*	SDL_SetClipRect(extSurf, extRect); //preventing blitting outside of that rect
 
 	const BlitterWithRotationVal blitterWithRotation = CSDL_Ext::getBlitterWithRotation(extSurf);
 	const BlitterWithRotationVal blitterWithRotationAndAlpha = CSDL_Ext::getBlitterWithRotationAndAlpha(extSurf);
@@ -480,7 +480,7 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 			const TerrainTile2 & tile = ttiles[pos.x][pos.y][pos.z];
 			const TerrainTile &tinfo = map->terrain[pos.x][pos.y][pos.z];
 
-			SDL_Rect sr;
+			Gfx::Rect sr;
 			sr.x=srx;
 			sr.y=sry;
 			sr.h=sr.w=32;
@@ -488,36 +488,36 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 			//blit terrain with river/road
 			if(tile.terbitmap)
 			{ //if custom terrain graphic - use it
-				SDL_Rect temp_rect = genRect(sr.h, sr.w, 0, 0);
-				CSDL_Ext::blitSurface(tile.terbitmap, &temp_rect, extSurf, &sr);
+//*				SDL_Rect temp_rect = genRect(sr.h, sr.w, 0, 0);
+//*				CSDL_Ext::blitSurface(tile.terbitmap, &temp_rect, extSurf, &sr);
 			}
 			else //use default terrain graphic
 			{
-                blitterWithRotation(terrainGraphics[tinfo.terType][tinfo.terView],rtile, extSurf, sr, tinfo.extTileFlags%4);
+//*               blitterWithRotation(terrainGraphics[tinfo.terType][tinfo.terView],rtile, extSurf, sr, tinfo.extTileFlags%4);
 			}
             if(tinfo.riverType) //print river if present
 			{
-                blitterWithRotationAndAlpha(staticRiverDefs[tinfo.riverType-1]->ourImages[tinfo.riverDir].bitmap,rtile, extSurf, sr, (tinfo.extTileFlags>>2)%4);
+//*               blitterWithRotationAndAlpha(staticRiverDefs[tinfo.riverType-1]->ourImages[tinfo.riverDir].bitmap,rtile, extSurf, sr, (tinfo.extTileFlags>>2)%4);
 			}
 
 			//Roads are shifted by 16 pixels to bottom. We have to draw both parts separately
             if (pos.y > 0 && map->terrain[pos.x][pos.y-1][pos.z].roadType != ERoadType::NO_ROAD)
 			{ //part from top tile
 				const TerrainTile &topTile = map->terrain[pos.x][pos.y-1][pos.z];
-				Rect source(0, 16, 32, 16);
-				Rect dest(sr.x, sr.y, sr.w, sr.h/2);
-                blitterWithRotationAndAlpha(roadDefs[topTile.roadType - 1]->ourImages[topTile.roadDir].bitmap, source, extSurf, dest, (topTile.extTileFlags>>4)%4);
+				Gfx::Rect source(0, 16, 32, 16);
+				Gfx::Rect dest(sr.x, sr.y, sr.w, sr.h/2);
+//*             blitterWithRotationAndAlpha(roadDefs[topTile.roadType - 1]->ourImages[topTile.roadDir].bitmap, source, extSurf, dest, (topTile.extTileFlags>>4)%4);
 			}
 
             if(tinfo.roadType != ERoadType::NO_ROAD) //print road from this tile
 			{
-				Rect source(0, 0, 32, 32);
-				Rect dest(sr.x, sr.y+16, sr.w, sr.h/2);
-                blitterWithRotationAndAlpha(roadDefs[tinfo.roadType-1]->ourImages[tinfo.roadDir].bitmap, source, extSurf, dest, (tinfo.extTileFlags>>4)%4);
+				Gfx::Rect source(0, 0, 32, 32);
+				Gfx::Rect dest(sr.x, sr.y+16, sr.w, sr.h/2);
+//*             blitterWithRotationAndAlpha(roadDefs[tinfo.roadType-1]->ourImages[tinfo.roadDir].bitmap, source, extSurf, dest, (tinfo.extTileFlags>>4)%4);
 			}
 
 			//blit objects
-			const std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > &objects = tile.objects;
+			const std::vector < std::pair<const CGObjectInstance*,Gfx::Rect> > &objects = tile.objects;
 			for(size_t h=0; h < objects.size(); ++h)
 			{
 				const CGObjectInstance *obj = objects[h].first;
@@ -536,9 +536,9 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 				if(puzzleMode && (obj->isVisitable() || std::find(notBlittedInPuzzleMode, notBlittedInPuzzleMode+1, obj->ID) != notBlittedInPuzzleMode+1)) //?
 					continue;
 
- 				SDL_Rect sr2(sr); 
+ 				Gfx::Rect sr2(sr); 
 
-				SDL_Rect pp = objects[h].second;
+				Gfx::Rect pp = objects[h].second;
 				pp.h = sr.h;
 				pp.w = sr.w;
 
@@ -608,12 +608,12 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 								break;
 							}
 						}
-						CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr2);
+//*						CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr2);
 
 						//printing flag
 						pp.y+=IMGVAL*2-32;
 						sr2.y-=16;
-						CSDL_Ext::blitSurface((graphics->*flg)[color.getNum()]->ourImages[gg+heroAnim%IMGVAL+35].bitmap, &pp, extSurf, &sr2);
+//*						CSDL_Ext::blitSurface((graphics->*flg)[color.getNum()]->ourImages[gg+heroAnim%IMGVAL+35].bitmap, &pp, extSurf, &sr2);
 					}
 					else //hero / boat stands still
 					{
@@ -626,20 +626,20 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 								break;
 							}
 						}
-						CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr2);
+//*						CSDL_Ext::blit8bppAlphaTo24bpp(tb,&pp,extSurf,&sr2);
 
 						//printing flag
 						if(flg  
 							&&  obj->pos.x == top_tile.x + bx  
 							&&  obj->pos.y == top_tile.y + by)
 						{
-							SDL_Rect bufr = sr2;
+							Gfx::Rect bufr(sr2);
 							bufr.x-=2*32;
 							bufr.y-=1*32;
 							bufr.h = 64;
 							bufr.w = 96;
-							if(bufr.x-extRect->x>-64)
-								CSDL_Ext::blitSurface((graphics->*flg)[color.getNum()]->ourImages[getHeroFrameNum(dir, false) *8+(heroAnim/4)%IMGVAL].bitmap, NULL, extSurf, &bufr);
+//*							if(bufr.x-extRect->x>-64)
+//*								CSDL_Ext::blitSurface((graphics->*flg)[color.getNum()]->ourImages[getHeroFrameNum(dir, false) *8+(heroAnim/4)%IMGVAL].bitmap, NULL, extSurf, &bufr);
 						}
 					}
 				}
@@ -651,11 +651,12 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 					//setting appropriate flag color
 					if(color < PlayerColor::PLAYER_LIMIT || color==PlayerColor::NEUTRAL)
 						CSDL_Ext::setPlayerColor(bitmap, color);
-
+/*
 					if( obj->hasShadowAt(top_tile.x + bx - obj->pos.x, top_tile.y + by - obj->pos.y) )
 						CSDL_Ext::blit8bppAlphaTo24bpp(bitmap,&pp,extSurf,&sr2);
 					else
 						CSDL_Ext::blitSurface(bitmap,&pp,extSurf,&sr2);
+*/
 				}
 			}
 			//objects blitted
@@ -665,7 +666,7 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 			{
 				if(bx == grailPosRel.x && by == grailPosRel.y)
 				{
-					CSDL_Ext::blit8bppAlphaTo24bpp(graphics->heroMoveArrows->ourImages[0].bitmap, NULL, extSurf, &sr);
+//*					CSDL_Ext::blit8bppAlphaTo24bpp(graphics->heroMoveArrows->ourImages[0].bitmap, NULL, extSurf, &sr);
 				}
 			}
 		}
@@ -692,10 +693,10 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 			if (pos.x < 0 || pos.x >= sizes.x ||
 				pos.y < 0 || pos.y >= sizes.y)
 			{
-				SDL_Rect temp_rect = genRect(sr.h, sr.w, 0, 0);
+				Gfx::Rect temp_rect = genRect(sr.h, sr.w, 0, 0);
 
-				CSDL_Ext::blitSurface(ttiles[pos.x][pos.y][top_tile.z].terbitmap,
-								&temp_rect,extSurf,&sr);
+//*				CSDL_Ext::blitSurface(ttiles[pos.x][pos.y][top_tile.z].terbitmap,
+//*								&temp_rect,extSurf,&sr);
 			}
 			else 
 			{
@@ -790,11 +791,11 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 	//applying sepia / gray effect
 	if(puzzleMode)
 	{
-		CSDL_Ext::applyEffect(extSurf, extRect, static_cast<int>(!ADVOPT.puzzleSepia));
+//*		CSDL_Ext::applyEffect(extSurf, extRect, static_cast<int>(!ADVOPT.puzzleSepia));
 	}
 	//sepia / gray effect applied
 
-	SDL_SetClipRect(extSurf, &prevClip); //restoring clip_rect
+//*	SDL_SetClipRect(extSurf, &prevClip); //restoring clip_rect
 }
 
 std::pair<SDL_Surface *, bool> CMapHandler::getVisBitmap( const int3 & pos, const std::vector< std::vector< std::vector<ui8> > > & visibilityMap ) const
@@ -869,17 +870,17 @@ bool CMapHandler::printObject(const CGObjectInstance *obj)
 	{
 		for(int fy=0; fy<tilesH; ++fy)
 		{
-			SDL_Rect cr;
+			Gfx::Rect cr;
 			cr.w = 32;
 			cr.h = 32;
 			cr.x = fx*32;
 			cr.y = fy*32;
-			std::pair<const CGObjectInstance*,SDL_Rect> toAdd = std::make_pair(obj, cr);
+			std::pair<const CGObjectInstance*,Gfx::Rect> toAdd = std::make_pair(obj, cr);
 			if((obj->pos.x + fx - tilesW+1)>=0 && (obj->pos.x + fx - tilesW+1)<ttiles.size()-frameW && (obj->pos.y + fy - tilesH+1)>=0 && (obj->pos.y + fy - tilesH+1)<ttiles[0].size()-frameH)
 			{
 				TerrainTile2 & curt = ttiles[obj->pos.x + fx - tilesW+1][obj->pos.y + fy - tilesH+1][obj->pos.z];
 
-				std::vector< std::pair<const CGObjectInstance*,SDL_Rect> >::iterator i = curt.objects.begin();
+				std::vector< std::pair<const CGObjectInstance*,Gfx::Rect> >::iterator i = curt.objects.begin();
 				for(; i != curt.objects.end(); i++)
 				{
 					OCM_HLP cmp;
@@ -911,7 +912,7 @@ bool CMapHandler::hideObject(const CGObjectInstance *obj)
 		{
 			if((obj->pos.x + fx - bitmap->w/32+1)>=0 && (obj->pos.x + fx - bitmap->w/32+1)<ttiles.size()-frameW && (obj->pos.y + fy - bitmap->h/32+1)>=0 && (obj->pos.y + fy - bitmap->h/32+1)<ttiles[0].size()-frameH)
 			{
-				std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > & ctile = ttiles[obj->pos.x + fx - bitmap->w/32+1][obj->pos.y + fy - bitmap->h/32+1][obj->pos.z].objects;
+				std::vector < std::pair<const CGObjectInstance*,Gfx::Rect> > & ctile = ttiles[obj->pos.x + fx - bitmap->w/32+1][obj->pos.y + fy - bitmap->h/32+1][obj->pos.z].objects;
 				for(size_t dd=0; dd < ctile.size(); ++dd)
 				{
 					if(ctile[dd].first->id==obj->id)
@@ -1086,7 +1087,7 @@ void CMapHandler::getTerrainDescr( const int3 &pos, std::string & out, bool terN
 	out.clear();
 	TerrainTile2 & tt = ttiles[pos.x][pos.y][pos.z];
 	const TerrainTile &t = map->terrain[pos.x][pos.y][pos.z];
-	for(std::vector < std::pair<const CGObjectInstance*,SDL_Rect> >::const_iterator i = tt.objects.begin(); i != tt.objects.end(); i++)
+	for(std::vector < std::pair<const CGObjectInstance*,Gfx::Rect> >::const_iterator i = tt.objects.begin(); i != tt.objects.end(); i++)
 	{
 		if(i->first->ID == Obj::HOLE) //Hole
 		{

+ 3 - 3
client/mapHandler.h

@@ -3,6 +3,7 @@
 
 #include "../lib/int3.h"
 #include "SDL.h"
+#include "Gfx/Basic.h"
 
 /*
  * mapHandler.h, part of VCMI engine
@@ -22,14 +23,13 @@ class CGObjectInstance;
 class CDefHandler;
 struct TerrainTile;
 struct SDL_Surface;
-//struct SDL_Rect;
 class CDefEssential;
 
 struct TerrainTile2
 {
 	SDL_Surface * terbitmap; //bitmap of terrain
 
-	std::vector < std::pair<const CGObjectInstance*,SDL_Rect> > objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
+	std::vector < std::pair<const CGObjectInstance*,Gfx::Rect> > objects; //pointers to objects being on this tile with rects to be easier to blit this tile on screen
 	TerrainTile2();
 };
 
@@ -124,7 +124,7 @@ public:
 	void roadsRiverTerrainInit();
 	void prepareFOWDefs();
 
-	void terrainRect(int3 top_tile, ui8 anim, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap, bool otherHeroAnim, ui8 heroAnim, SDL_Surface * extSurf, const SDL_Rect * extRect, int moveX, int moveY, bool puzzleMode, int3 grailPosRel) const;
+	void terrainRect(int3 top_tile, ui8 anim, const std::vector< std::vector< std::vector<ui8> > > * visibilityMap, bool otherHeroAnim, ui8 heroAnim, SDL_Surface * extSurf, const Gfx::Rect * extRect, int moveX, int moveY, bool puzzleMode, int3 grailPosRel) const;
 	void updateWater();
 	ui8 getHeroFrameNum(ui8 dir, bool isMoving) const; //terrainRect helper function
 	void validateRectTerr(SDL_Rect * val, const SDL_Rect * ext); //terrainRect helper

+ 88 - 8
config/artifacts.json

@@ -2356,7 +2356,17 @@
 				}
 			],
 			"id" : 146,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
+			"growing":
+			{
+				"bonusesPerLevel":
+				[
+					{
+						"level": 6,
+						"bonus": ["PRIMARY_SKILL", 1, "primSkill.attack", 0]
+					}
+				]
+			}
 		},
 		"mithrilMail":
 		{
@@ -2368,7 +2378,17 @@
 				}
 			],
 			"id" : 147,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
+			"growing":
+			{
+				"bonusesPerLevel":
+				[
+					{
+						"level": 1,
+						"bonus": ["STACK_HEALTH", 1, 0, 0]
+					}
+				]
+			}
 		},
 		"swordOfSharpness":
 		{
@@ -2381,7 +2401,17 @@
 				}
 			],
 			"id" : 148,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
+			"growing":
+			{
+				"bonusesPerLevel":
+				[
+					{
+						"level": 1,
+						"bonus": ["CREATURE_DAMAGE", 1, 0, 0]
+					}
+				]
+			}
 		},
 		"helmOfImmortality": //TODO: implement
 		{
@@ -2398,7 +2428,17 @@
 				}
 			],
 			"id" : 150,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
+			"growing":
+			{
+				"bonusesPerLevel":
+				[
+					{
+						"level": 10,
+						"bonus": ["CREATURE_ENCHANT_POWER", 1, 0, 0]
+					}
+				]
+			}
 		},
 		"bootsOfHaste":
 		{
@@ -2410,17 +2450,46 @@
 				}
 			],
 			"id" : 151,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
+			"growing":
+			{
+				"bonusesPerLevel":
+				[
+					{
+						"level": 10,
+						"bonus": ["STACKS_SPEED", 1, 0, 0]
+					}
+				]
+			}
 		},
 		"bowOfSeeking":
 		{
 			"id" : 152,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
+			"growing":
+			{
+				"id": 152, //bow of seeking
+				"thresholdBonuses":
+				[
+					{
+						"level": 5,
+						"bonus": ["SHOOTER", 0, 0, 0]
+					},
+					{
+						"level": 25,
+						"bonus": ["NO_WALL_PENALTY", 0, 0, 0]
+					},
+					{
+						"level": 50,
+						"bonus": ["NO_DISTANCE_PENALTY", 0, 0, 0]
+					}
+				]
+			}
 		},
 		"dragonEyeRing": //TODO: implement
 		{
 			"id" : 153,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
 		},
 		"hardenedShield":
 		{
@@ -2433,7 +2502,18 @@
 				}
 			],
 			"id" : 154,
-			"type" : ["COMMANDER"]
+			"type" : ["COMMANDER"],
+			"growing":
+			{
+				"id": 153, //hardened shield
+				"bonusesPerLevel":
+				[
+					{
+						"level": 6,
+						"bonus": ["PRIMARY_SKILL", 1, "primSkill.defence", 0]
+					}
+				]
+			}
 		},
 		"slavasRingOfPower": //TODO: implement if possible
 		{

+ 526 - 0
config/bonuses.json

@@ -0,0 +1,526 @@
+//TODO: selector-based config
+// SECONDARY_SKILL_PREMY
+// school immunities
+// LEVEL_SPELL_IMMUNITY
+
+{
+	"ADDITIONAL_ATTACK":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_DOUBLE"
+		}
+	},
+	
+	"ADDITIONAL_RETALIATION":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_RETAIL1"
+		}
+	},
+	
+	"AIR_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  ""
+		}
+	},
+			
+	"ATTACKS_ALL_ADJACENT":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_ROUND"
+		}
+	},
+
+	"BLOCKS_RETALIATION":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_RETAIL"
+		}
+	},
+	
+	"CATAPULT":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/Catapult"
+		}
+	},	
+	
+	"CHANGES_SPELL_COST_FOR_ALLY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_MANA"
+		}
+	},
+	
+	"CHANGES_SPELL_COST_FOR_ENEMY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/MagicDamper"
+		}
+	},
+
+	"CHARGE_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/ChargeImmune"
+		}
+	},
+	
+	"DAEMON_SUMMONING":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/RiseDemons"
+		}
+	},
+	
+	"DARKNESS":
+	{
+	},				
+	
+	"DEATH_STARE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_DEATH"
+		}
+	},	
+		
+	"DEFENSIVE_STANCE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_DEFBON"
+		}
+	},
+		
+	"DOUBLE_DAMAGE_CHANCE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_DBLOW"
+		}
+	},
+
+	"DRAGON_NATURE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_DRAGON"
+		}
+	},
+	
+	"DIRECT_DAMAGE_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_SPDIR"
+		}
+	},
+
+	"EARTH_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  ""
+		}
+	},
+					
+	"ENCHANTER":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_CAST1"
+		}
+	},
+	
+	"ENCHANTED":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_BLESS"
+		}
+	},		
+
+
+
+	"ENEMY_DEFENCE_REDUCTION":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_RDEF"
+		}
+	},
+	
+	"FIRE_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  ""
+		}
+	},
+	
+	"FIRE_SHIELD":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/FireShield"
+		}		
+	},
+	"FEAR":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_FEAR"
+		}
+	},
+	
+	"FEARLESS":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_FEARL"
+		}
+	},
+	
+	"FLYING":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_FLY"
+		}
+
+	},		
+
+	"FREE_SHOOTING":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_SHOOTA"
+		}
+
+	},
+
+	"FULL_HP_REGENERATION":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_TROLL"
+		}
+	},
+			
+	"HATE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_HATE"
+		}
+	},
+	
+	"HEALER":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/Healer"
+		}
+	},
+	
+	"HP_REGENERATION":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_TROLL"
+		}
+	},
+	"JOUSTING":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_CHAMP"
+		}
+	},
+	
+	"KING1":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_KING1"
+		}
+	},
+	
+	"KING2":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_KING2"
+		}
+	},
+	
+	"KING3":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_KING3"
+		}
+	},
+	
+	"LEVEL_SPELL_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  ""
+		}
+	},
+	
+	"LIFE_DRAIN":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/DrainLife"
+		}
+	},
+
+	"MANA_CHANNELING":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/ManaChannel"
+		}
+	},
+	"MANA_DRAIN":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/ManaDrain"
+		}
+	},
+
+	"MAGIC_MIRROR":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/MagicMirror"
+		}
+	},
+
+	"MAGIC_RESISTANCE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_DWARF"
+		}
+	},
+
+	"MIND_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_MIND"
+		}
+	},
+
+	"NO_DISTANCE_PENALTY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_DIST"
+		}
+	},
+	"NO_MELEE_PENALTY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_MELEE"
+		}
+	},
+	
+	"NO_MORALE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_MORAL"
+		}		
+	},		
+	"NO_WALL_PENALTY":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_OBST"
+		}
+	},
+
+	"NON_LIVING":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/NonLiving"
+		}
+	},	
+
+	"RANDOM_SPELLCASTER":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/RandomBoost"
+		}
+	},
+
+	"RECEPTIVE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_NOFRIM"
+		}
+	},
+	"REBIRTH":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_REBIRTH"
+		}
+	},
+								
+	"RETURN_AFTER_STRIKE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_HARPY"
+		}
+	},
+	
+	"SECONDARY_SKILL_PREMY":
+	{
+		"hidden": true
+		//todo: selector based config
+	},
+	
+	"SELF_LUCK":
+	{
+		"graphics":
+		{
+			"icon":  ""
+		}
+	},
+	
+	"SELF_MORALE":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_MINOT"
+		}
+	},
+	
+	"SHOOTER":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_SHOOT"
+		}
+	},	
+	"SPELLCASTER":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_CASTER"
+		}
+	},
+					
+	"SPELL_AFTER_ATTACK":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_CAST"
+		}
+	},
+	
+	"SPELL_BEFORE_ATTACK":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_CAST2"
+		}
+	},
+	
+	"SPELL_DAMAGE_REDUCTION":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_GOLEM"
+		}
+	},
+
+	"SPELL_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  "" //todo: configurable use from spell handler
+		}
+	},
+
+	
+	"SPELL_LIKE_ATTACK":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/SpellLikeAttack"
+		}
+	},
+			
+	"SPELL_RESISTANCE_AURA":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_UNIC"
+		}
+	},
+
+	"TWO_HEX_ATTACK_BREATH":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_BREATH"
+		}
+	},
+
+
+	"THREE_HEADED_ATTACK":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/ThreeHeaded"
+		}
+	},
+
+	"UNDEAD":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_UNDEAD"
+		}
+	},
+	"UNLIMITED_RETALIATIONS":
+	{
+		"graphics":
+		{
+			"icon":  "zvs/Lib1.res/E_RETAIL1"
+		}
+	},
+	"WATER_IMMUNITY":
+	{
+		"graphics":
+		{
+			"icon":  ""
+		}
+	}
+}
+

+ 387 - 0
config/bonuses_texts.json

@@ -0,0 +1,387 @@
+// macros:
+// ${val} - value of bonuses; Selector: type,subtype
+// ${subtype.creature} - creature name 
+// ${subtype.spell} - spell name
+// ${MR} - magic resistance of bearer
+
+
+{
+	"ADDITIONAL_ATTACK":
+	{
+		"name": "Double Strike",
+		"description": "Attacks twice"
+	},
+	
+	"ADDITIONAL_RETALIATION":
+	{
+		"name": "Additional retaliations",
+		"description": "May Retaliate ${val} extra times"
+	},
+	
+	"AIR_IMMUNITY":
+	{
+		"name": "Immune to Air",
+		"description": ""
+	},
+			
+	"ATTACKS_ALL_ADJACENT":
+	{
+		"name": "Attack all around",
+		"description": "Attacks all adjacent enemies"
+	},
+
+	"BLOCKS_RETALIATION":
+	{
+		"name": "No retaliation",
+		"description": "Enemy cannot Retaliate"
+	},
+	
+	"CATAPULT":
+	{
+		"name": "Catapult",
+		"description": "Attacks siege walls"
+	},	
+	
+	"CHANGES_SPELL_COST_FOR_ALLY":
+	{
+		"name": "Reduce Casting Cost (${val})",
+		"description": "Reduce Casting Cost for hero"
+	},
+	
+	"CHANGES_SPELL_COST_FOR_ENEMY":
+	{
+		"name": "Magic Damper (${val})",
+		"description": "Increase Cost of enemy spells"
+	},
+
+	"CHARGE_IMMUNITY":
+	{
+		"name": "Immune to Charge",
+		"description": "Immune to Champion charge"
+	},
+	
+	"DAEMON_SUMMONING":
+	{
+		"name": "Summoner (${subtype.creature})",
+		"description": "Can rise creatures from corpses" 
+	},
+	
+	"DARKNESS":		
+	{
+		"name": "Darness cover",
+		"description": "Adds ${val} darkness radius"
+	},
+			
+	"DEATH_STARE":
+	{
+		"name": "Death Stare (${val}%)",
+		"description": "Chance to kill single creature"
+	},	
+		
+	"DEFENSIVE_STANCE":
+	{
+		"name": "Defense Bonus",
+		"description": "+${val} Defense when defending"
+	},
+		
+	"DOUBLE_DAMAGE_CHANCE":
+	{
+		"name": "Death Blow",
+		"description": "${val}% chance for double damage"
+	},
+
+	"DRAGON_NATURE":
+	{
+		"name": "Dragon",
+		"description": "Creature has a Dragon Nature"
+	},
+	
+	"DIRECT_DAMAGE_IMMUNITY":
+	{
+		"name": "Direct Damage Immunity",
+		"description": "Immune to direct damage spells"
+	},
+
+	"EARTH_IMMUNITY":
+	{
+		"name": "Immune to Earth",
+		"description": ""
+	},
+					
+	"ENCHANTER":
+	{
+		"name": "Enchanter (${subtype.spell})",
+		"description": "Casts mass spell every turn"
+	},
+	
+	"ENCHANTED":
+	{
+		"name": "Enchanted (${subtype.spell})",
+		"description": "Affected by permanent spell"
+	},		
+
+	"ENEMY_DEFENCE_REDUCTION":
+	{
+		"name": "Reduce Enemy Defense (${val}%)",
+		"description": "Reduces Defense for one attack"
+	},
+	
+	"FIRE_IMMUNITY":
+	{
+		"name": "Immune to Fire",
+		"description": ""
+	},
+
+	"FIRE_SHIELD":
+	{
+		"name": "Fire Shield (${val}%)",
+		"description": "Reflects melee damage"		
+	},
+	"FEAR":
+	{
+		"name": "Fear",
+		"description": "Causes Fear on an enemy stack"
+	},
+	
+	"FEARLESS":
+	{
+		"name": "Fearless",
+		"description": "Immune to Fear ability"
+	},
+	
+	"FLYING":
+	{
+		"name": "Fly",
+		"description": "Can Fly (ignores obstacles)"
+	},		
+
+	"FREE_SHOOTING":
+	{
+		"name": "Shoot Close",
+		"description": "Can shoot in Close Combat"
+	},
+
+	"FULL_HP_REGENERATION":
+	{
+		"name": "Regeneration",
+		"description": "May Regenerate full Health"
+	},
+			
+	"HATE":
+	{
+		"name": "Hates ${subtype.creature}",
+		"description": "Does ${val}% more damage"
+	},
+	
+	"HEALER":
+	{
+		"name": "Healer",
+		"description": "Heals allied units"
+	},
+	
+	"HP_REGENERATION":
+	{
+		"name": "Regeneration",
+		"description": "Heals ${val} hit points every round"
+	},
+	"JOUSTING":
+	{
+		"name": "Champion Charge",
+		"description": "+5% damage per hex travelled"
+	},
+	
+	"KING1":
+	{
+	},
+	
+	"KING2":
+	{
+	},
+	
+	"KING3":
+	{
+	},
+	
+	"LEVEL_SPELL_IMMUNITY":
+	{
+		"name": "Spell immunity 1-${val}",
+		"description": "Immune to spells levels 1-${val}"
+	},
+	
+	"LIFE_DRAIN":
+	{
+		"name": "Drain life (${val}%)",
+		"description": "Drains ${val}% of damage dealt"
+	},
+
+	"MANA_CHANNELING":
+	{
+		"name": "Magic Channel ${val}%",
+		"description": "Gives mana spent by enemy"
+	},
+	"MANA_DRAIN":
+	{
+		"name": "Mana Drain",
+		"description": "Drains ${val} mana every turn"
+	},
+
+	"MAGIC_MIRROR":
+	{
+		"name": "Magic Mirror (${val}%)",
+		"description": "${val}% chance to redirects offensive spell to enemy"
+	},
+
+	"MAGIC_RESISTANCE":
+	{
+		"name": "Magic Resistance(${MR}%)",
+		"description": "${MR}% chance to resist enemy spell"
+	},
+
+	"MIND_IMMUNITY":
+	{
+		"name": "Immune to mind spells",
+		"description": ""
+	},
+
+	"NO_DISTANCE_PENALTY":
+	{
+		"name": "No distance penalty",
+		"description": "Full damage from any distance"
+	},
+	"NO_MELEE_PENALTY":
+	{
+		"name": "No melee penalty",
+		"description": "Creature has no Melee Penalty"
+	},
+	
+	
+	"NO_MORALE":
+	{
+	
+	},	
+		
+	"NO_WALL_PENALTY":
+	{
+		"name": "No wall penalty",
+		"description": "Full damage during siege"
+	},
+
+	"NON_LIVING":
+	{
+		"name": "Non living",
+		"description": "Immunity to many effects"
+	},	
+
+	"RANDOM_SPELLCASTER":
+	{
+		"name": "Random spellcaster",
+		"description": "Can cast random spell"
+	},
+
+	"RECEPTIVE":
+	{
+		"name": "Receptive",
+		"description": "No Immunity to Friendly Spells"
+	},
+	"REBIRTH":
+	{
+		"name": "Rebirth (${val}%)",
+		"description": "${val}% of stack will rise after death"
+	},
+								
+	"RETURN_AFTER_STRIKE":
+	{
+		"name": "Attack and Return",
+		"description": "Returns after melee attack"
+	},
+	
+	"SELF_LUCK":
+	{
+		"name": "Positive luck",
+		"description": "Always has Positive Luck"
+	},
+	
+	"SELF_MORALE":
+	{
+		"name": "Positive morale",
+		"description": "Always has Positive Morale"
+	},
+	
+	"SHOOTER":
+	{
+		"name": "Ranged",
+		"description": "Creature can shoot"
+	},	
+	"SPELLCASTER":
+	{
+		"name": "Spellcaster (${subtype.spell})",
+		"description": "Can cast spells"
+	},
+					
+	"SPELL_AFTER_ATTACK":
+	{
+		"name": "Caster - ${subtype.spell}",
+		"description": "${val}% chance to cast after attack"
+	},
+	
+	"SPELL_BEFORE_ATTACK":
+	{
+		"name": "Caster - ${subtype.spell}",
+		"description": "${val}% chance to cast before attack"
+	},
+	
+	"SPELL_DAMAGE_REDUCTION":
+	{
+		"name": "Spell Resistance",
+		"description": "Damage from spells reduced ${val}%."
+	},
+
+	"SPELL_IMMUNITY":
+	{
+		"name": "Immune to ${subtype.spell}",
+		"description": ""
+	},
+
+	
+	"SPELL_LIKE_ATTACK":
+	{
+		"name": "Spell-like attack",
+		"description": "Attacks with ${subtype.spell}"
+	},
+			
+	"SPELL_RESISTANCE_AURA":
+	{
+		"name": "Aura of Resistance",
+		"description": "Nearby stacks get ${val}% resistance"
+	},
+
+	"TWO_HEX_ATTACK_BREATH":
+	{
+		"name": "Breath",
+		"description": "Breath Attack (2-hex range)"
+	},
+
+
+
+	"THREE_HEADED_ATTACK":
+	{
+		"name": "Three-headed attack",
+		"description": "Attacks three adjacent units"
+	},
+
+	"UNDEAD":
+	{
+		"name": "Undead",
+		"description": "Creature is Undead"
+	},
+	"UNLIMITED_RETALIATIONS":
+	{
+		"name": "Unlimited retaliations",
+		"description": "Retaliate any number of attacks"
+	},
+	"WATER_IMMUNITY":
+	{
+		"name": "Immune to Water",
+		"description": ""
+	}
+}

+ 0 - 66
config/bonusnames.json

@@ -1,66 +0,0 @@
-{
-	"bonuses":
-		[
-			{ "id": "ADDITIONAL_RETALIATION", "name": "Additional retaliations", "description": "May Retaliate %d extra times" },
-			{ "id": "ATTACKS_ALL_ADJACENT", "name": "Attack all around", "description": "Attacks all adjacent enemies" },
-			{ "id": "RETURN_AFTER_STRIKE", "name": "Attack and Return", "description": "Returns after melee attack" },
-			{ "id": "SPELL_RESISTANCE_AURA", "name": "Aura of Resistance", "description": "Nearby stacks get %d% resistance" },
-			{ "id": "TWO_HEX_ATTACK_BREATH", "name": "Breath", "description": "Breath Attack (2-hex range)" },
-			{ "id": "SPELL_AFTER_ATTACK", "name": "Caster - %s", "description": "%d% chance to cast after attack" },
-			{ "id": "SPELL_BEFORE_ATTACK", "name": "Caster - %s", "description": "%d% chance to cast before attack" },
-			{ "id": "SPELL_LIKE_ATTACK", "name": "Spell-like attack", "description": "Attacks with %s" },
-			{ "id": "CATAPULT", "name": "Catapult", "description": "Attacks siege walls" },
-			{ "id": "JOUSTING", "name": "Champion Charge", "description": "+5% damage per hex travelled" },
-			{ "id": "DOUBLE_DAMAGE_CHANCE", "name": "Death Blow", "description": "%d% chance for double damage" },
-			{ "id": "DEFENSIVE_STANCE", "name": "Defense Bonus", "description": "+%d Defense when defending" },
-			{ "id": "ADDITIONAL_ATTACK", "name": "Double Strike", "description": "Attacks twice" },
-			{ "id": "DRAGON_NATURE", "name": "Dragon", "description": "Creature has a Dragon Nature" },
-			{ "id": "LIFE_DRAIN", "name": "Drain life (%d%)", "description": "Drains life equal to damage dealt" },
-			{ "id": "FEAR", "name": "Fear", "description": "Causes Fear on an enemy stack" },
-			{ "id": "FEARLESS", "name": "Fearless", "description": "Immune to Fear ability" },
-			{ "id": "FLYING", "name": "Fly", "description": "Can Fly (ignores obstacles)" },
-			{ "id": "HATE", "name": "Hates %s", "description": "Does %d% more damage" },
-			{ "id": "HEALER", "name": "Healer", "description": "Heals allied units" },
-			{ "id": "SPELL_IMMUNITY", "name": "Immune to %s", "description": "" },
-			{ "id": "CHARGE_IMMUNITY", "name": "Immune to Charge", "description": "Immune to Champion charge" },
-			{ "id": "MANA_CHANNELING", "name": "Magic Channel %d%", "description": "Gives mana spent by enemy" },
-			{ "id": "MANA_DRAIN", "name": "Mana Drain", "description": "Drains %d mana every turn" },
-			{ "id": "CHANGES_SPELL_COST_FOR_ENEMY", "name": "Magic Damper (%d)", "description": "Increase Cost of enemy spells" },
-			{ "id": "MAGIC_MIRROR", "name": "Magic Mirror (%d%)", "description": "Redirects offensive spell to enemy" },
-			{ "id": "MAGIC_RESISTANCE", "name": "Magic Resistance", "description": "%d% chance to resist enemy spell" },
-			{ "id": "NO_DISTANCE_PENALTY", "name": "No distance penalty", "description": "Full damage from any distance" },
-			{ "id": "NO_MELEE_PENALTY", "name": "No melee penalty", "description": "Creature has no Melee Penalty" },
-			{ "id": "NO_WALL_PENALTY", "name": "No wall penalty", "description": "Full damage during siege" },
-			{ "id": "BLOCKS_RETALIATION", "name": "No retaliation", "description": "Enemy cannot Retaliate" },
-			{ "id": "NON_LIVING", "name": "Non living", "description": "Immunity to many effects" },
-			{ "id": "SELF_LUCK", "name": "Positive luck", "description": "Always has Positive Luck" },
-			{ "id": "SELF_MORALE", "name": "Positive morale", "description": "Always has Positive Morale" },
-			{ "id": "SHOOTER", "name": "Ranged", "description": "Creature can shoot" },
-			{ "id": "CHANGES_SPELL_COST_FOR_ALLY", "name": "Reduce Casting Cost (%d)", "description": "Reduce Casting Cost for hero" },
-			{ "id": "ENEMY_DEFENCE_REDUCTION", "name": "Reduce Enemy Defense (%d%)", "description": "Reduces Defense for one attack" },
-			{ "id": "FULL_HP_REGENERATION", "name": "Regeneration", "description": "May Regenerate full Health" },
-			{ "id": "HP_REGENERATION", "name": "Regeneration", "description": "Heals %d hit points every round" },
-			{ "id": "FREE_SHOOTING", "name": "Shoot Close", "description": "Can shoot in Close Combat" },
-			{ "id": "LEVEL_SPELL_IMMUNITY", "name": "Spell immunity 1-%d", "description": "Immune to spells levels 1-%d" },
-			{ "id": "SPELL_DAMAGE_REDUCTION", "name": "Spell Resistance", "description": "Damage from spells reduced %d%." },
-			{ "id": "THREE_HEADED_ATTACK", "name": "Three-headed attack", "description": "Attacks three adjacent units" },
-			{ "id": "UNDEAD", "name": "Undead", "description": "Creature is Undead" },
-			{ "id": "UNLIMITED_RETALIATIONS", "name": "Unlimited retaliations", "description": "Retaliate any number of attacks" },
-			{ "id": "DEATH_STARE", "name": "Death Stare (%d%)", "description": "Chance to kill single creature" },
-			{ "id": "FIRE_IMMUNITY", "name": "Immune to Fire", "description": "" },
-			{ "id": "WATER_IMMUNITY", "name": "Immune to Water", "description": "" },
-			{ "id": "AIR_IMMUNITY", "name": "Immune to Air", "description": "" },
-			{ "id": "EARTH_IMMUNITY", "name": "Immune to Earth", "description": "" },
-			{ "id": "MIND_IMMUNITY", "name": "Immune to mind spells", "description": "" },
-			{ "id": "DIRECT_DAMAGE_IMMUNITY", "name": "Direct Damage Immunity", "description": "Immune to direct damage spells" },
-			{ "id": "RECEPTIVE", "name": "Receptive", "description": "No Immunity to Friendly Spells" },
-			{ "id": "REBIRTH", "name": "Rebirth (%d%)", "description": "Stack will rise after death" },
-			{ "id": "SPELLCASTER", "name": "Spellcaster (%s)", "description": "Can cast spells" },
-			{ "id": "ENCHANTER", "name": "Enchanter (%s)", "description": "Casts mass spell every turn" },
-			{ "id": "ENCHANTED", "name": "Enchanted (%s)", "description": "Affected by permanent spell" },
-			{ "id": "FIRE_SHIELD", "name": "Fire Shield (%d%)", "description": "Reflects melee damage" },
-			{ "id": "MAGIC_MIRROR", "name": "Magic Mirror (%d%)", "description": "Chance to reflect hostile spell" },
-			{ "id": "RANDOM_SPELLCASTER", "name": "Random spellcaster", "description": "Can cast random spell" },
-			{ "id": "DAEMON_SUMMONING", "name": "Summoner (%s)", "description": "Can rise creatures from corpses" }
-		]
-}

+ 0 - 81
config/commanders.json

@@ -37,86 +37,5 @@
 		{"ability": ["JOUSTING", 0, 0, 0 ], "skills": [3, 4]},
 		{"ability": ["DEATH_STARE", 1, 1, 0 ], "skills": [3,5]},
 		{"ability": ["FLYING", 0, 0, 0 ], "skills": [4,5]}
-	],
-	"artifacts":
-	[
-		{
-			"id": 146, //axe of smashing
-			"bonusesPerLevel":
-			[
-				{
-					"level": 6,
-					"bonus": ["PRIMARY_SKILL", 1, "primSkill.attack", 0]
-				}
-			]
-		},
-		{
-			"id": 147, //mithril mail
-			"bonusesPerLevel":
-			[
-				{
-					"level": 1,
-					"bonus": ["STACK_HEALTH", 1, 0, 0]
-				}
-			]
-		},
-		{
-			"id": 148, //sword of sharpness
-			"bonusesPerLevel":
-			[
-				{
-					"level": 1,
-					"bonus": ["CREATURE_DAMAGE", 1, 0, 0]
-				}
-			]
-		},
-		{
-			"id": 150, //pendant of sorcery
-			"bonusesPerLevel":
-			[
-				{
-					"level": 10,
-					"bonus": ["CREATURE_ENCHANT_POWER", 1, 0, 0]
-				}
-			]
-		},
-		{
-			"id": 151, //boots of haste
-			"bonusesPerLevel":
-			[
-				{
-					"level": 10,
-					"bonus": ["STACKS_SPEED", 1, 0, 0]
-				}
-			]
-		},
-		{
-			"id": 152, //bow of seeking
-			"thresholdBonuses":
-			[
-				{
-					"level": 5,
-					"bonus": ["SHOOTER", 0, 0, 0]
-				},
-				{
-					"level": 25,
-					"bonus": ["NO_WALL_PENALTY", 0, 0, 0]
-				},
-				{
-					"level": 50,
-					"bonus": ["NO_DISTANCE_PENALTY", 0, 0, 0]
-				}
-			]
-		},
-		{
-			"id": 153, //hardened shield
-			"bonusesPerLevel":
-			[
-				{
-					"level": 6,
-					"bonus": ["PRIMARY_SKILL", 1, "primSkill.defence", 0]
-				}
-			]
-		}
 	]
 }

+ 6 - 0
config/gameConfig.json

@@ -45,4 +45,10 @@
 		"config/heroes/conflux.json",
 		"config/heroes/special.json"
 	],
+	
+	"bonuses" :
+	[
+		"config/bonuses.json",
+		"config/bonuses_texts.json"
+	]
 }

+ 180 - 36
config/heroClasses.json

@@ -1,38 +1,182 @@
 {
-	// battle animations for heroes, ordered by faction
-	"heroBattleAnim" :
-	[
-		{ "male" : "CH00.DEF",  "female" : "CH01.DEF" },
-		{ "male" : "CH02.DEF",  "female" : "CH03.DEF" },
-		{ "male" : "CH05.DEF",  "female" : "CH04.DEF" },
-		{ "male" : "CH06.DEF",  "female" : "CH07.DEF" },
-		{ "male" : "CH08.DEF",  "female" : "CH09.DEF" },
-		{ "male" : "CH010.DEF", "female" : "CH11.DEF" },
-		{ "male" : "CH013.DEF", "female" : "CH012.DEF" },
-		{ "male" : "CH014.DEF", "female" : "CH015.DEF" },
-		{ "male" : "CH16.DEF",  "female" : "CH17.DEF" }
-	],
-
-	// map animations for heroes, ordered by hero class
-	"heroMapAnim" :
-	[
-		"AH00_.def",
-		"AH01_.def",
-		"AH02_.def",
-		"AH03_.def",
-		"AH04_.def",
-		"AH05_.def",
-		"AH06_.def",
-		"AH07_.def",
-		"AH08_.def",
-		"AH09_.def",
-		"AH10_.def",
-		"AH11_.def",
-		"AH12_.def",
-		"AH13_.def",
-		"AH14_.def",
-		"AH15_.def",
-		"AH16_.def",
-		"AH17_.def"
-	]
+	"knight":
+	{
+		"id": 0,
+		"faction" : "castle",
+		"animation":
+		{
+			"battle" : { "male" : "CH00.DEF",  "female" : "CH01.DEF" },
+			"map":     { "male" : "AH00_.def", "female" : "AH00_.def" }
+		}
+	},
+	"cleric" :
+	{
+		"id": 1,
+		"faction" : "castle",
+		"animation":
+		{
+			"battle" : { "male" : "CH00.DEF",  "female" : "CH01.DEF" },
+			"map":     { "male" : "AH01_.def", "female" : "AH01_.def" }
+		}
+	},
+	"ranger" :
+	{
+		"id": 2,
+		"faction" : "rampart",
+		"animation":
+		{
+			"battle" : { "male" : "CH02.DEF",  "female" : "CH03.DEF" },
+			"map":     { "male" : "AH02_.def", "female" : "AH02_.def" }
+		}
+	},
+	"druid" :
+	{
+		"id": 3,
+		"faction" : "rampart",
+		"animation":
+		{
+			"battle" : { "male" : "CH02.DEF",  "female" : "CH03.DEF" },
+			"map":     { "male" : "AH03_.def", "female" : "AH03_.def" }
+		}
+	},
+	"alchemist" :
+	{
+		"id": 4,
+		"faction" : "tower",
+		"animation":
+		{
+			"battle" : { "male" : "CH05.DEF",  "female" : "CH04.DEF" },
+			"map":     { "male" : "AH04_.def", "female" : "AH04_.def" }
+		}
+	},
+	"wizard" :
+	{
+		"id": 5,
+		"faction" : "tower",
+		"animation":
+		{
+			"battle" : { "male" : "CH05.DEF",  "female" : "CH04.DEF" },
+			"map":     { "male" : "AH05_.def", "female" : "AH05_.def" }
+		}
+	},
+	"demoniac" :
+	{
+		"id": 6,
+		"faction" : "inferno",
+		"animation":
+		{
+			"battle" : { "male" : "CH06.DEF",  "female" : "CH07.DEF" },
+			"map":     { "male" : "AH06_.def", "female" : "AH06_.def" }
+		}
+	},
+	"heretic" :
+	{
+		"id": 7,
+		"faction" : "inferno",
+		"animation":
+		{
+			"battle" : { "male" : "CH06.DEF",  "female" : "CH07.DEF" },
+			"map":     { "male" : "AH07_.def", "female" : "AH07_.def" }
+		}
+	},
+	"deathknight" :
+	{
+		"id": 8,
+		"faction" : "necropolis",
+		"animation":
+		{
+			"battle" : { "male" : "CH08.DEF",  "female" : "CH09.DEF" },
+			"map":     { "male" : "AH08_.def", "female" : "AH08_.def" }
+		}
+	},
+	"necromancer" :
+	{
+		"id": 9,
+		"faction" : "necropolis",
+		"animation":
+		{
+			"battle" : { "male" : "CH08.DEF",  "female" : "CH09.DEF" },
+			"map":     { "male" : "AH09_.def", "female" : "AH09_.def" }
+		}
+	},
+	"warlock" :
+	{
+		"id": 10,
+		"faction" : "dungeon",
+		"animation":
+		{
+			"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
+			"map":     { "male" : "AH10_.def", "female" : "AH10_.def" }
+		}
+	},
+	"overlord" :
+	{
+		"id": 11,
+		"faction" : "dungeon",
+		"animation":
+		{
+			"battle" : { "male" : "CH010.DEF", "female" : "CH11.DEF" },
+			"map":     { "male" : "AH11_.def", "female" : "AH11_.def" }
+		}
+	},
+	"barbarian" :
+	{
+		"id": 12,
+		"faction" : "stronghold",
+		"animation":
+		{
+			"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
+			"map":     { "male" : "AH12_.def", "female" : "AH12_.def" }
+		}
+	},
+	"battlemage" :
+	{
+		"id": 13,
+		"faction" : "stronghold",
+		"animation":
+		{
+			"battle" : { "male" : "CH013.DEF", "female" : "CH012.DEF" },
+			"map":     { "male" : "AH13_.def", "female" : "AH13_.def" }
+		}
+	},
+	"beastmaster" :
+	{
+		"id": 14,
+		"faction" : "fortress",
+		"animation":
+		{
+			"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
+			"map":     { "male" : "AH14_.def", "female" : "AH14_.def" }
+		}
+	},
+	"witch" :
+	{
+		"id": 15,
+		"faction" : "fortress",
+		"animation":
+		{
+			"battle" : { "male" : "CH014.DEF", "female" : "CH015.DEF" },
+			"map":     { "male" : "AH15_.def", "female" : "AH15_.def" }
+		}
+	},
+	"planeswalker" :
+	{
+		"id": 16,
+		"faction" : "conflux",
+		"animation":
+		{
+			"battle" : { "male" : "CH16.DEF",  "female" : "CH17.DEF" },
+			"map":     { "male" : "AH16_.def", "female" : "AH16_.def" }
+		}
+	},
+	"elementalist" :
+	{
+		"id": 17,
+		"faction" : "conflux",
+		"animation":
+		{
+			"battle" : { "male" : "CH16.DEF",  "female" : "CH17.DEF" },
+			"map":     { "male" : "AH17_.def", "female" : "AH17_.def" }
+		}
+	}
 }

+ 148 - 129
lib/CArtHandler.cpp

@@ -24,40 +24,27 @@ using namespace boost::assign;
  */
 
 extern boost::rand48 ran;
-
-const std::map<std::string, CArtifact::EartClass> artifactClassMap = boost::assign::map_list_of
-	("TREASURE", CArtifact::ART_TREASURE)
-	("MINOR", CArtifact::ART_MINOR)
-	("MAJOR", CArtifact::ART_MAJOR)
-	("RELIC", CArtifact::ART_RELIC)
-	("SPECIAL", CArtifact::ART_SPECIAL);
-
-#define ART_BEARER(x) ( #x, ArtBearer::x )
-	const std::map<std::string, int> artifactBearerMap = boost::assign::map_list_of ART_BEARER_LIST;
-#undef ART_BEARER
-
-#define ART_POS(x) ( #x, ArtifactPosition::x )
-
-const std::map<std::string, ArtifactPosition> artifactPositionMap = boost::assign::map_list_of
-	ART_POS(HEAD)
-	ART_POS(SHOULDERS)
-	ART_POS(NECK)
-	ART_POS(RIGHT_HAND)
-	ART_POS(LEFT_HAND)
-	ART_POS(TORSO)
-	ART_POS(RIGHT_RING)
-	ART_POS(LEFT_RING)
-	ART_POS(FEET)
-	ART_POS(MISC1)
-	ART_POS(MISC2)
-	ART_POS(MISC3)
-	ART_POS(MISC4)
-	ART_POS(MISC5)
-	ART_POS(MACH1)
-	ART_POS(MACH2)
-	ART_POS(MACH3)
-	ART_POS(MACH4)
-	ART_POS(SPELLBOOK); //no need to specify commander / stack position?
+// Note: list must match entries in ArtTraits.txt
+#define ART_POS_LIST    \
+	ART_POS(SPELLBOOK)  \
+	ART_POS(MACH4)      \
+	ART_POS(MACH3)      \
+	ART_POS(MACH2)      \
+	ART_POS(MACH1)      \
+	ART_POS(MISC5)      \
+	ART_POS(MISC4)      \
+	ART_POS(MISC3)      \
+	ART_POS(MISC2)      \
+	ART_POS(MISC1)      \
+	ART_POS(FEET)       \
+	ART_POS(LEFT_RING)  \
+	ART_POS(RIGHT_RING) \
+	ART_POS(TORSO)      \
+	ART_POS(LEFT_HAND)  \
+	ART_POS(RIGHT_HAND) \
+	ART_POS(NECK)       \
+	ART_POS(SHOULDERS)  \
+	ART_POS(HEAD);
 
 const std::string & CArtifact::Name() const
 {
@@ -166,15 +153,12 @@ void CArtHandler::load(bool onlyTxt)
 	if (onlyTxt)
 		return; // looks to be broken anyway...
 
-	std::vector<ui16> artSlots;
-	artSlots += 17, 16, 15, 14, 13, 18, 12, 11, 10, 9, 8, 7, 6, 5, 4, 3, 2, 1, 0;
-
-	growingArtifacts += ArtifactID::AXE_OF_SMASHING, ArtifactID::MITHRIL_MAIL,
-		ArtifactID::SWORD_OF_SHARPNESS, ArtifactID::PENDANT_OF_SORCERY, ArtifactID::BOOTS_OF_HASTE,
-		ArtifactID::BOW_OF_SEEKING, ArtifactID::DRAGON_EYE_RING;
+	#define ART_POS(x) (  #x)
+	const std::vector<std::string> artSlots = boost::assign::list_of ART_POS_LIST;
+	#undef ART_POS
 
-	static std::map<char, CArtifact::EartClass> classes =
-	  map_list_of('S',CArtifact::ART_SPECIAL)('T',CArtifact::ART_TREASURE)('N',CArtifact::ART_MINOR)('J',CArtifact::ART_MAJOR)('R',CArtifact::ART_RELIC);
+	static std::map<char, std::string> classes =
+	  map_list_of('S',"SPECIAL")('T',"TREASURE")('N',"MINOR")('J',"MAJOR")('R',"RELIC");
 
 	CLegacyConfigParser parser("DATA/ARTRAITS.TXT");
 	CLegacyConfigParser events("DATA/ARTEVENT.TXT");
@@ -184,74 +168,54 @@ void CArtHandler::load(bool onlyTxt)
 
 	std::map<ui32,ui8>::iterator itr;
 
-	for (ArtifactID i=ArtifactID(0); i<GameConstants::ARTIFACTS_QUANTITY; i.advance(1))
+	std::vector<JsonNode> h3Data;
+
+	for (size_t i = 0; i < GameConstants::ARTIFACTS_QUANTITY; i++)
 	{
-		CArtifact *art;
-		if (vstd::contains (growingArtifacts, i))
-		{
-			art = new CGrowingArtifact();
-		}
-		else
-		{
-			art = new CArtifact();
-		}
-		art->id=i;
-		art->iconIndex=i;
-		art->name = parser.readString();
-		art->eventText = events.readString();
-		events.endLine();
+		JsonNode artData;
 
-		art->price= parser.readNumber();
+		artData["graphics"]["iconIndex"].Float() = i;
+		artData["text"]["name"].String() = parser.readString();
+		artData["text"]["event"].String() = events.readString();
+		artData["value"].Float() = parser.readNumber();
 
 		for(size_t j=0; j<artSlots.size(); ++j)
 		{
 			if(parser.readString() == "x")
-				art->possibleSlots[ArtBearer::HERO].push_back(ArtifactPosition(artSlots[j]));
-		}
-		art->aClass = classes[parser.readString()[0]];
-
-		//load description and remove quotation marks
-		art->description = parser.readString();
-
-		parser.endLine();
-
-		if(onlyTxt) // FIXME: pointer to art will be lost. Bug?
-			continue;
-
-		artifacts.push_back(art);
-	}
-
-	if (VLC->modh->modules.COMMANDERS)
-	{ //TODO: move all artifacts config to separate json file
-		const JsonNode config(ResourceID("config/commanders.json"));
-		BOOST_FOREACH(const JsonNode &artifact, config["artifacts"].Vector())
-		{
-			auto ga = dynamic_cast <CGrowingArtifact *>(artifacts[artifact["id"].Float()].get());
-			BOOST_FOREACH (auto b, artifact["bonusesPerLevel"].Vector())
-			{
-				ga->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector())));
-			}
-			BOOST_FOREACH (auto b, artifact["thresholdBonuses"].Vector())
 			{
-				ga->thresholdBonuses.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector())));
+				artData["slot"].Vector().push_back(JsonNode());
+				artData["slot"].Vector().back().String() = artSlots.at(j);
 			}
 		}
+		artData["class"].String() = classes[parser.readString()[0]];
+		artData["text"]["description"].String() = parser.readString();
+
+		parser.endLine();
+		events.endLine();
+		h3Data.push_back(artData);
 	}
 
-	if(onlyTxt)
-		return;
+	artifacts.resize(GameConstants::ARTIFACTS_QUANTITY);
 
 	JsonNode config(ResourceID("config/artifacts.json"));
 
 	BOOST_FOREACH(auto & node, config["artifacts"].Struct())
 	{
-		int numeric = node.second["id"].asInteger();
-		CArtifact * art = artifacts[numeric];
+		int numeric = node.second["id"].Float();
+		JsonNode & artData = h3Data[numeric];
+		JsonUtils::merge(artData, node.second);
 
-		loadArtifactJson(art, node.second);
+		artifacts[numeric] = loadArtifact(artData);
+		artifacts[numeric]->id = ArtifactID(numeric);
 
 		VLC->modh->identifiers.registerObject ("artifact." + node.first, numeric);
 	}
+
+	for (size_t i=0; i < artifacts.size(); i++)
+	{
+		if (artifacts[i] == nullptr)
+			tlog0 << "Warning: artifact with id " << i << " is missing!\n";
+	}
 }
 
 void CArtHandler::load(std::string objectID, const JsonNode & node)
@@ -266,7 +230,16 @@ void CArtHandler::load(std::string objectID, const JsonNode & node)
 
 CArtifact * CArtHandler::loadArtifact(const JsonNode & node)
 {
-	CArtifact * art = new CArtifact;
+	CArtifact * art;
+
+	if (!VLC->modh->modules.COMMANDERS || node["growing"].isNull())
+		art = new CArtifact();
+	else
+	{
+		CGrowingArtifact * growing = new CGrowingArtifact();
+		loadGrowingArt(growing, node);
+		art = growing;
+	}
 
 	const JsonNode & text = node["text"];
 	art->name        = text["name"].String();
@@ -283,59 +256,90 @@ CArtifact * CArtHandler::loadArtifact(const JsonNode & node)
 	art->advMapDef = graphics["map"].String();
 
 	art->price = node["value"].asInteger();
+
+	loadSlots(art, node);
+	loadClass(art, node);
+	loadType(art, node);
+	loadComponents(art, node);
+
+	BOOST_FOREACH (auto b, node["bonuses"].Vector())
 	{
-		auto it = artifactClassMap.find (node["class"].String());
-		if (it != artifactClassMap.end())
+		auto bonus = JsonUtils::parseBonus (b);
+		bonus->sid = art->id;
+		art->addNewBonus (bonus);
+	}
+	return art;
+}
+
+void CArtHandler::addSlot(CArtifact * art, const std::string & slotID)
+{
+#define ART_POS(x) ( #x, ArtifactPosition::x )
+	static const std::map<std::string, ArtifactPosition> artifactPositionMap = boost::assign::map_list_of ART_POS_LIST;
+#undef ART_POS
+
+	if (slotID == "MISC")
+	{
+		art->possibleSlots[ArtBearer::HERO] += ArtifactPosition::MISC1, ArtifactPosition::MISC2, ArtifactPosition::MISC3, ArtifactPosition::MISC4, ArtifactPosition::MISC5;
+	}
+	else if (slotID == "RING")
+	{
+		art->possibleSlots[ArtBearer::HERO] += ArtifactPosition::LEFT_RING, ArtifactPosition::RIGHT_RING;
+	}
+	else
+	{
+		auto it = artifactPositionMap.find (slotID);
+		if (it != artifactPositionMap.end())
 		{
-			art->aClass = it->second;
+			auto slot = it->second;
+			art->possibleSlots[ArtBearer::HERO].push_back (slot);
 		}
 		else
-		{
-			tlog2 << "Warning! Artifact rarity " << node["class"].String() << " not recognized!";
-			art->aClass = CArtifact::ART_SPECIAL;
-		}
+			tlog2 << "Warning! Artifact slot " << slotID << " not recognized!";
 	}
+}
 
+void CArtHandler::loadSlots(CArtifact * art, const JsonNode & node)
+{
 	if (!node["slot"].isNull()) //we assume non-hero slots are irrelevant?
 	{
-		std::string slotName = node["slot"].String();
-		if (slotName == "MISC")
-		{
-			//unfortunatelly slot ids aare not continuous
-			art->possibleSlots[ArtBearer::HERO] += ArtifactPosition::MISC1, ArtifactPosition::MISC2, ArtifactPosition::MISC3, ArtifactPosition::MISC4, ArtifactPosition::MISC5;
-		}
-		else if (slotName == "RING")
-		{
-			art->possibleSlots[ArtBearer::HERO] += ArtifactPosition::LEFT_RING, ArtifactPosition::RIGHT_RING;
-		}
+		if (node["slot"].getType() == JsonNode::DATA_STRING)
+			addSlot(art, node["slot"].String());
 		else
 		{
-
-			auto it = artifactPositionMap.find (slotName);
-			if (it != artifactPositionMap.end())
-			{
-				auto slot = it->second;
-				art->possibleSlots[ArtBearer::HERO].push_back (slot);
-			}
-			else
-				tlog2 << "Warning! Artifact slot " << node["slot"].String() << " not recognized!";
+			BOOST_FOREACH (const JsonNode & slot, node["slot"].Vector())
+				addSlot(art, slot.String());
 		}
 	}
-
-	loadArtifactJson(art, node);
-
-	return art;
 }
 
-void CArtHandler::loadArtifactJson(CArtifact * art, const JsonNode & artifact)
+void CArtHandler::loadClass(CArtifact * art, const JsonNode & node)
 {
-	BOOST_FOREACH (auto b, artifact["bonuses"].Vector())
+	static const std::map<std::string, CArtifact::EartClass> artifactClassMap = boost::assign::map_list_of
+		("TREASURE", CArtifact::ART_TREASURE)
+		("MINOR", CArtifact::ART_MINOR)
+		("MAJOR", CArtifact::ART_MAJOR)
+		("RELIC", CArtifact::ART_RELIC)
+		("SPECIAL", CArtifact::ART_SPECIAL);
+
+	auto it = artifactClassMap.find (node["class"].String());
+	if (it != artifactClassMap.end())
 	{
-		auto bonus = JsonUtils::parseBonus (b);
-		bonus->sid = art->id;
-		art->addNewBonus (bonus);
+		art->aClass = it->second;
 	}
-	BOOST_FOREACH (const JsonNode & b, artifact["type"].Vector())
+	else
+	{
+		tlog2 << "Warning! Artifact rarity " << node["class"].String() << " not recognized!";
+		art->aClass = CArtifact::ART_SPECIAL;
+	}
+}
+
+void CArtHandler::loadType(CArtifact * art, const JsonNode & node)
+{
+#define ART_BEARER(x) ( #x, ArtBearer::x )
+	static const std::map<std::string, int> artifactBearerMap = boost::assign::map_list_of ART_BEARER_LIST;
+#undef ART_BEARER
+
+	BOOST_FOREACH (const JsonNode & b, node["type"].Vector())
 	{
 		auto it = artifactBearerMap.find (b.String());
 		if (it != artifactBearerMap.end())
@@ -356,11 +360,14 @@ void CArtHandler::loadArtifactJson(CArtifact * art, const JsonNode & artifact)
 		else
 			tlog2 << "Warning! Artifact type " << b.String() << " not recognized!";
 	}
+}
 
-	if (!artifact["components"].isNull())
+void CArtHandler::loadComponents(CArtifact * art, const JsonNode & node)
+{
+	if (!node["components"].isNull())
 	{
 		art->constituents.reset(new std::vector<CArtifact *>());
-		BOOST_FOREACH (auto component, artifact["components"].Vector())
+		BOOST_FOREACH (auto component, node["components"].Vector())
 		{
 			VLC->modh->identifiers.requestIdentifier("artifact." + component.String(), [=](si32 id)
 			{
@@ -373,6 +380,18 @@ void CArtHandler::loadArtifactJson(CArtifact * art, const JsonNode & artifact)
 	}
 }
 
+void CArtHandler::loadGrowingArt(CGrowingArtifact * art, const JsonNode & node)
+{
+	BOOST_FOREACH (auto b, node["growing"]["bonusesPerLevel"].Vector())
+	{
+		art->bonusesPerLevel.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector())));
+	}
+	BOOST_FOREACH (auto b, node["growing"]["thresholdBonuses"].Vector())
+	{
+		art->thresholdBonuses.push_back (std::pair <ui16, Bonus> (b["level"].Float(), *JsonUtils::parseBonus (b["bonus"].Vector())));
+	}
+}
+
 ArtifactID CArtHandler::creatureToMachineID(CreatureID id)
 {
 	int dif = 142;

+ 15 - 10
lib/CArtHandler.h

@@ -59,8 +59,8 @@ public:
 	bool isBig () const;
 
 	int getArtClassSerial() const; //0 - treasure, 1 - minor, 2 - major, 3 - relic, 4 - spell scroll, 5 - other
-	std::string nodeName() const OVERRIDE;
-	void addNewBonus(Bonus *b) OVERRIDE;
+	std::string nodeName() const override;
+	void addNewBonus(Bonus *b) override;
 
 	virtual void levelUpArtifact (CArtifactInstance * art){};
 
@@ -112,7 +112,7 @@ public:
 
 	//CArtifactInstance(int aid);
 
-	std::string nodeName() const OVERRIDE;
+	std::string nodeName() const override;
 	void deserializationFix();
 	void setType(CArtifact *Art);
 
@@ -161,11 +161,11 @@ public:
 
 	std::vector<ConstituentInfo> constituentsInfo;
 
-	bool canBePutAt(const CArtifactSet *artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const OVERRIDE;
-	bool canBeDisassembled() const OVERRIDE;
-	void putAt(ArtifactLocation al) OVERRIDE;
-	void removeFrom(ArtifactLocation al) OVERRIDE;
-	bool isPart(const CArtifactInstance *supposedPart) const OVERRIDE;
+	bool canBePutAt(const CArtifactSet *artSet, ArtifactPosition slot, bool assumeDestRemoved = false) const override;
+	bool canBeDisassembled() const override;
+	void putAt(ArtifactLocation al) override;
+	void removeFrom(ArtifactLocation al) override;
+	bool isPart(const CArtifactInstance *supposedPart) const override;
 
 	void createConstituents();
 	void addAsConstituent(CArtifactInstance *art, ArtifactPosition slot);
@@ -187,6 +187,13 @@ public:
 
 class DLL_LINKAGE CArtHandler //handles artifacts
 {
+	void addSlot(CArtifact * art, const std::string & slotID);
+	void loadSlots(CArtifact * art, const JsonNode & node);
+	void loadClass(CArtifact * art, const JsonNode & node);
+	void loadType(CArtifact * art, const JsonNode & node);
+	void loadComponents(CArtifact * art, const JsonNode & node);
+	void loadGrowingArt(CGrowingArtifact * art, const JsonNode & node);
+
 	void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype = -1, Bonus::ValueType valType = Bonus::BASE_NUMBER, shared_ptr<ILimiter> limiter = shared_ptr<ILimiter>(), int additionalinfo = 0);
 	void giveArtBonus(ArtifactID aid, Bonus::BonusType type, int val, int subtype, shared_ptr<IPropagator> propagator, int additionalinfo = 0);
 	void giveArtBonus(ArtifactID aid, Bonus *bonus);
@@ -204,8 +211,6 @@ public:
 	/// load one artifact from json config
 	CArtifact * loadArtifact(const JsonNode & node);
 
-	void loadArtifactJson(CArtifact * art, const JsonNode & node);
-
 	void addBonuses(CArtifact *art, const JsonNode &bonusList);
 
 	void fillList(std::vector<CArtifact*> &listToBeFilled, CArtifact::EartClass artifactClass); //fills given empty list with allowed artifacts of gibven class. No side effects

+ 21 - 6
lib/CBattleCallback.cpp

@@ -1483,14 +1483,29 @@ ESpellCastProblem::ESpellCastProblem CBattleInfoCallback::battleIsImmune(const C
 		switch (spell->id) //TODO: more general logic for new spells?
 		{
 		case SpellID::CLONE:
-			if (caster) //TODO: how about stacks casting Clone?
 			{
+				//can't clone already cloned creature
 				if (vstd::contains(subject->state, EBattleStackState::CLONED))
-					return ESpellCastProblem::STACK_IMMUNE_TO_SPELL; //can't clone already cloned creature
-				int maxLevel = (std::max(caster->getSpellSchoolLevel(spell), (ui8)1) + 4);
-				int creLevel = subject->getCreature()->level;
-				if (maxLevel < creLevel) //tier 1-5 for basic, 1-6 for advanced, 1-7 for expert
-					return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;
+					return ESpellCastProblem::STACK_IMMUNE_TO_SPELL; 
+				//TODO: how about stacks casting Clone?
+				//currently Clone casted by stack is assumed Expert level
+				ui8 schoolLevel;
+				if (caster)
+				{
+					schoolLevel = caster->getSpellSchoolLevel(spell);
+				}
+				else
+				{
+					schoolLevel = 3;
+				}
+				
+				if (schoolLevel < 3)
+				{
+					int maxLevel = (std::max(schoolLevel, (ui8)1) + 4);
+					int creLevel = subject->getCreature()->level;
+					if (maxLevel < creLevel) //tier 1-5 for basic, 1-6 for advanced, any level for expert
+						return ESpellCastProblem::STACK_IMMUNE_TO_SPELL;	
+				}					
 			}
 			break;
 		case SpellID::DISPEL_HELPFUL_SPELLS:

+ 6 - 6
lib/CBonusTypeHandler.cpp

@@ -299,12 +299,12 @@ void CBonusTypeHandler::load(const JsonNode& config)
 		if(it == bonusNameMap.end())
 		{
 			//TODO: new bonus
-			CBonusType bt;
-			loadItem(node.second, bt);
-			
-			auto new_id = bonusTypes.size();
-			
-			bonusTypes.push_back(bt);
+//			CBonusType bt;
+//			loadItem(node.second, bt);
+//			
+//			auto new_id = bonusTypes.size();
+//			
+//			bonusTypes.push_back(bt);
 			
 			tlog2 << "Adding new bonuses not implemented (" << node.first << ")" << std::endl;
 		}

+ 1 - 1
lib/CCreatureHandler.cpp

@@ -353,7 +353,7 @@ void CCreatureHandler::load()
 
 	BOOST_FOREACH(auto & node, config.Struct())
 	{
-		int creatureID = node.second["id"].Float();
+		int creatureID = node.second["id"].asInteger();
 		CCreature *c = creatures[creatureID];
 
 		loadCreatureJson(c, node.second);

+ 13 - 13
lib/CGameState.cpp

@@ -2927,12 +2927,12 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
 		BOOST_FOREACH(const JsonNode &stackNode, n["army"].Vector())
 		{
 			ss.stacks[i].type = CreatureID((si32)stackNode.Vector()[0].Float());
-			ss.stacks[i].count = stackNode.Vector()[1].Float();
+			ss.stacks[i].count = stackNode.Vector()[1].asInteger();
 			i++;
 		}
 
 		if(n["heroid"].getType() == JsonNode::DATA_FLOAT)
-			ss.heroId = n["heroid"].Float();
+			ss.heroId = n["heroid"].asInteger();
 		else
 			ss.heroId = -1;
 
@@ -2942,8 +2942,8 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
 		BOOST_FOREACH(const JsonNode &skillNode, n["heroSecSkills"].Vector())
 		{
 			std::pair<si32, si8> secSkill;
-			secSkill.first = skillNode.Vector()[0].Float();
-			secSkill.second = skillNode.Vector()[1].Float();
+			secSkill.first = skillNode.Vector()[0].asInteger();
+			secSkill.second = skillNode.Vector()[1].asInteger();
 			ss.heroSecSkills.push_back(secSkill);
 		}
 
@@ -2969,14 +2969,14 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
 		auto oi = make_shared<CObstacleInstance>();
 		if(n.getType() == JsonNode::DATA_VECTOR)
 		{
-			oi->ID = n.Vector()[0].Float();
-			oi->pos = n.Vector()[1].Float();
+			oi->ID = n.Vector()[0].asInteger();
+			oi->pos = n.Vector()[1].asInteger();
 		}
 		else
 		{
 			assert(n.getType() == JsonNode::DATA_FLOAT);
 			oi->ID = 21;
-			oi->pos = n.Float();
+			oi->pos = n.asInteger();
 		}
 		oi->uniqueID = ret.obstacles.size();
 		ret.obstacles.push_back(oi);
@@ -2985,13 +2985,13 @@ DuelParameters DuelParameters::fromJSON(const std::string &fname)
 	BOOST_FOREACH(const JsonNode &n, duelData["creatures"].Vector())
 	{
 		CusomCreature cc;
-		cc.id = n["id"].Float();
+		cc.id = n["id"].asInteger();
 
 #define retreive(name)								\
 	if(n[ #name ].getType() == JsonNode::DATA_FLOAT)\
-	cc.name = n[ #name ].Float();			\
+		cc.name = n[ #name ].asInteger();			\
 	else											\
-	cc.name = -1;
+		cc.name = -1;
 
 		retreive(attack);
 		retreive(defense);
@@ -3013,11 +3013,11 @@ TeamState::TeamState()
 void CPathfinder::initializeGraph()
 {
 	CGPathNode ***graph = out.nodes;
-	for(si32 i=0; i < out.sizes.x; ++i)
+	for(size_t i=0; i < out.sizes.x; ++i)
 	{
-		for(si32 j=0; j < out.sizes.y; ++j)
+		for(size_t j=0; j < out.sizes.y; ++j)
 		{
-			for(si32 k=0; k < out.sizes.z; ++k)
+			for(size_t k=0; k < out.sizes.z; ++k)
 			{
 				curPos = int3(i,j,k);
 				const TerrainTile *tinfo = &gs->map->terrain[i][j][k];

+ 32 - 27
lib/CHeroHandler.cpp

@@ -85,49 +85,54 @@ void CHeroClassHandler::load()
 	parser.endLine(); // header
 	parser.endLine();
 
+	std::vector<JsonNode> h3Data;
+
 	do
 	{
-		CHeroClass * hc = new CHeroClass;
+		JsonNode entry;
 
-		hc->name             = parser.readString();
-		hc->aggression       = parser.readNumber();
-		hc->id = heroClasses.size();
+		entry["name"].String() = parser.readString();
 
-		hc->primarySkillInitial   = parser.readNumArray<int>(GameConstants::PRIMARY_SKILLS);
-		hc->primarySkillLowLevel  = parser.readNumArray<int>(GameConstants::PRIMARY_SKILLS);
-		hc->primarySkillHighLevel = parser.readNumArray<int>(GameConstants::PRIMARY_SKILLS);
+		parser.readNumber(); // unused aggression
 
-		hc->secSkillProbability   = parser.readNumArray<int>(GameConstants::SKILL_QUANTITY);
+		for (size_t i=0; i < GameConstants::PRIMARY_SKILLS; i++)
+			entry["primarySkills"][PrimarySkill::names[i]].Float() = parser.readNumber();
 
-		for(int dd=0; dd<GameConstants::F_NUMBER; ++dd)
-		{
-			hc->selectionProbability[dd] = parser.readNumber();
-		}
+		for (size_t i=0; i < GameConstants::PRIMARY_SKILLS; i++)
+			entry["lowLevelChance"][PrimarySkill::names[i]].Float() = parser.readNumber();
 
-		VLC->modh->identifiers.requestIdentifier("faction." + ETownType::names[heroClasses.size()/2],
-		[=](si32 faction)
-		{
-			hc->faction = faction;
-		});
+		for (size_t i=0; i < GameConstants::PRIMARY_SKILLS; i++)
+			entry["highLevelChance"][PrimarySkill::names[i]].Float() = parser.readNumber();
+
+		for (size_t i=0; i < GameConstants::SKILL_QUANTITY; i++)
+			entry["secondarySkills"][NSecondarySkill::names[i]].Float() = parser.readNumber();
+
+		for(size_t i = 0; i < GameConstants::F_NUMBER; i++)
+			entry["tavern"][ETownType::names[i]].Float() = parser.readNumber();
 
-		heroClasses.push_back(hc);
-		VLC->modh->identifiers.registerObject("heroClass." + GameConstants::HERO_CLASSES_NAMES[hc->id], hc->id);
+		h3Data.push_back(entry);
 	}
 	while (parser.endLine() && !parser.isNextEntryEmpty());
 
-	const JsonNode & heroGraphics = JsonNode(ResourceID("config/heroClasses.json"));
+	JsonNode classConf = JsonNode(ResourceID("config/heroClasses.json"));
+	heroClasses.resize(GameConstants::F_NUMBER * 2);
 
-	for (size_t i=0; i<heroClasses.size(); i++)
+	BOOST_FOREACH(auto & node, classConf.Struct())
 	{
-		const JsonNode & battle = heroGraphics["heroBattleAnim"].Vector()[i/2];
+		int numeric = node.second["id"].Float();
+		JsonNode & classData = h3Data[numeric];
+		JsonUtils::merge(classData, node.second);
 
-		heroClasses[i]->imageBattleFemale = battle["female"].String();
-		heroClasses[i]->imageBattleMale = battle["male"].String();
+		heroClasses[numeric] = loadClass(classData);
+		heroClasses[numeric]->id = numeric;
 
-		const JsonNode & map = heroGraphics["heroMapAnim"].Vector()[i];
+		VLC->modh->identifiers.registerObject ("heroClass." + node.first, numeric);
+	}
 
-		heroClasses[i]->imageMapMale = map.String();
-		heroClasses[i]->imageMapFemale = map.String();
+	for (size_t i=0; i < heroClasses.size(); i++)
+	{
+		if (heroClasses[i] == nullptr)
+			tlog0 << "Warning: class with id " << i << " is missing!\n";
 	}
 }
 

+ 2 - 2
lib/CHeroHandler.h

@@ -98,7 +98,7 @@ class DLL_LINKAGE CHeroClass
 public:
 	std::string identifier;
 	std::string name; // translatable
-	double aggression;
+	//double aggression; // not used in vcmi.
 	TFaction faction;
 	ui8 id;
 
@@ -119,7 +119,7 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & identifier & name & faction & aggression;
+		h & identifier & name & faction;// & aggression;
 		h & primarySkillInitial   & primarySkillLowLevel;
 		h & primarySkillHighLevel & secSkillProbability;
 		h & selectionProbability;

+ 2 - 2
lib/CObjectHandler.cpp

@@ -813,7 +813,7 @@ void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= NULL*/)
 	if(!dst)
 		dst = this;
 
-	int howManyStacks = 0; //how many stacks will hero receives <1 - 3>
+	size_t howManyStacks = 0; //how many stacks will hero receives <1 - 3>
 	int pom = ran()%100;
 	int warMachinesGiven = 0;
 
@@ -826,7 +826,7 @@ void CGHeroInstance::initArmy(IArmyDescriptor *dst /*= NULL*/)
 
 	vstd::amin(howManyStacks, type->initialArmy.size());
 
-	for(int stackNo=0; stackNo < howManyStacks; stackNo++)
+	for(size_t stackNo=0; stackNo < howManyStacks; stackNo++)
 	{
 		auto & stack = type->initialArmy[stackNo];
 

+ 0 - 5
lib/StringConstants.h

@@ -26,11 +26,6 @@ namespace GameConstants
 	    "wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold", "mithril"
 	};
 
-	const std::string HERO_CLASSES_NAMES [F_NUMBER * 2] = {
-	    "knight",    "cleric",     "ranger",      "druid",       "alchemist",    "wizard",
-	    "demoniac",  "heretic",    "deathknight", "necromancer", "warlock",      "overlord",
-	    "barbarian", "battlemage", "beastmaster", "witch",       "planeswalker", "elementalist"
-	};
 	const std::string PLAYER_COLOR_NAMES [PlayerColor::PLAYER_LIMIT_I] = {
 		"red", "blue", "tan", "green", "orange", "purple", "teal", "pink"
 	};