浏览代码

- reorganized hero classes
- artifact iconIndex should work
- new file with hardcoded string constants: lib/StringConstants.h

Note: some minor bugs, will fix soon:
- slow to open hero window
- hero adventure map images serialization is broken\incorrect

Ivan Savenko 13 年之前
父节点
当前提交
ffe8b99369

+ 1 - 0
client/AdventureMapClasses.cpp

@@ -12,6 +12,7 @@
 #include "../lib/CTownHandler.h"
 #include "../lib/NetPacks.h"
 #include "../lib/CHeroHandler.h"
+#include "../lib/StringConstants.h"
 #include "CAdvmapInterface.h"
 #include "CAnimation.h"
 #include "CGameInfo.h"

+ 12 - 11
client/BattleInterface/CBattleInterface.cpp

@@ -239,7 +239,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 	//loading hero animations
 	if(hero1) // attacking hero
 	{
-		int type = hero1->type->heroType;
+		int type = hero1->type->heroClass->id;
 		if ( type % 2 )   type--;
 		if ( hero1->sex ) type++;
 		attackingHero = new CBattleHero(graphics->battleHeroes[type], false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : NULL, this);
@@ -251,7 +251,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet * army1, const CCreatureSe
 	}
 	if(hero2) // defending hero
 	{
-		int type = hero2->type->heroType;
+		int type = hero2->type->heroClass->id;
 		if ( type % 2 )   type--;
 		if ( hero2->sex ) type++;
 		defendingHero = new CBattleHero(graphics->battleHeroes[type ], true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : NULL, this);
@@ -1142,7 +1142,7 @@ void CBattleInterface::setBattleCursor(const int myNumber)
 	while (sectorCursor[(cursorIndex + i)%sectorCursor.size()] == -1) //Why hast thou forsaken me?
 		i = i <= 0 ? 1 - i : -i; // 0, 1, -1, 2, -2, 3, -3 etc..
 	int index = (cursorIndex + i)%sectorCursor.size(); //hopefully we get elements from sectorCursor
-	cursor->changeGraphic(1, sectorCursor[index]);
+	cursor->changeGraphic(ECursor::COMBAT, sectorCursor[index]);
 	switch (index)
 	{
 		case 0:
@@ -1182,7 +1182,7 @@ void CBattleInterface::bOptionsf()
 	if(spellDestSelectMode) //we are casting a spell
 		return;
 
-	CCS->curh->changeGraphic(0,0);
+	CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
 
 	Rect tempRect = genRect(431, 481, 160, 84);
 	tempRect += pos.topLeft();
@@ -1238,7 +1238,7 @@ void CBattleInterface::bFleef()
 void CBattleInterface::reallyFlee()
 {
 	giveCommand(BattleAction::RETREAT,0,0);
-	CCS->curh->changeGraphic(0, 0);
+	CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 }
 
 void CBattleInterface::reallySurrender()
@@ -1250,7 +1250,7 @@ void CBattleInterface::reallySurrender()
 	else
 	{
 		giveCommand(BattleAction::SURRENDER,0,0);
-		CCS->curh->changeGraphic(0, 0);
+		CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 	}
 }
 
@@ -1265,7 +1265,7 @@ void CBattleInterface::bSpellf()
 	if(spellDestSelectMode) //we are casting a spell
 		return;
 
-	CCS->curh->changeGraphic(0,0);
+	CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
 
 	if(!myTurn)
 		return;
@@ -1585,7 +1585,7 @@ void CBattleInterface::battleFinished(const BattleResult& br)
 
 void CBattleInterface::displayBattleFinished()
 {
-	CCS->curh->changeGraphic(0,0);
+	CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
 
 	SDL_Rect temp_rect = genRect(561, 470, (screen->w - 800)/2 + 165, (screen->h - 600)/2 + 19);
 	resWindow = new CBattleResultWindow(*bresult, temp_rect, this);
@@ -2076,7 +2076,7 @@ void CBattleInterface::endCastingSpell()
 	spellToCast = NULL;
 	sp = NULL;
 	spellDestSelectMode = false;
-	CCS->curh->changeGraphic(1, 6);
+	CCS->curh->changeGraphic(ECursor::COMBAT, ECursor::COMBAT_POINTER);
 
 	if (activeStack)
 	{
@@ -2762,7 +2762,8 @@ void CBattleInterface::handleHex(BattleHex myNumber, int eventType)
 	//used when hovering -> tooltip message and cursor to be set
 	std::string consoleMsg;
 	bool setCursor = true; //if we want to suppress setting cursor
-	int cursorType = ECursor::COMBAT, cursorFrame = ECursor::COMBAT_POINTER; //TODO: is this line used?
+	ECursor::ECursorTypes cursorType = ECursor::COMBAT;
+	int cursorFrame = ECursor::COMBAT_POINTER; //TODO: is this line used?
 	
 	//used when l-clicking -> action to be called upon the click
 	std::function<void()> realizeAction;
@@ -3256,7 +3257,7 @@ BattleHex CBattleInterface::fromWhichHexAttack(BattleHex myNumber)
 {
 	//TODO far too much repeating code
 	BattleHex destHex = -1;
-	switch(CCS->curh->number)
+	switch(CCS->curh->frame)
 	{
 	case 12: //from bottom right
 		{

+ 1 - 1
client/BattleInterface/CBattleInterfaceClasses.cpp

@@ -173,7 +173,7 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
 			if(myOwner->bfield[it]->hovered && myOwner->bfield[it]->strictHovered)
 				return;
 		}
-		CCS->curh->changeGraphic(0,0);
+		CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 
 		CSpellWindow * spellWindow = new CSpellWindow(genRect(595, 620, (screen->w - 620)/2, (screen->h - 595)/2), myHero, myOwner->curInt);
 		GH.pushInt(spellWindow);

+ 38 - 38
client/CAdvmapInterface.cpp

@@ -100,7 +100,7 @@ void CTerrainRect::mouseMoved (const SDL_MouseMotionEvent & sEvent)
 
 	if(tHovered != pom) //tile outside the map
 	{
-		CCS->curh->changeGraphic(0, 0);
+		CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 		return;
 	}
 
@@ -116,7 +116,7 @@ void CTerrainRect::hover(bool on)
 	if (!on)
 	{
 		adventureInt->statusbar.clear();
-		CCS->curh->changeGraphic(0,0);
+		CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
 	}
 	//Hoverable::hover(on);
 }
@@ -634,7 +634,7 @@ void CAdvMapInt::deactivate()
 	{
 		scrollingDir = 0;
 
-		CCS->curh->changeGraphic(0,0);
+		CCS->curh->changeGraphic(ECursor::ADVENTURE,0);
 		kingOverview.deactivate();
 		underground.deactivate();
 		questlog.deactivate();
@@ -1213,7 +1213,7 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
 {
 	if(!LOCPLINT->cb->isVisible(mapPos))
 	{
-		CCS->curh->changeGraphic(0, 0);
+		CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 		statusbar.clear();
 		return;
 	}
@@ -1247,18 +1247,18 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
 		{
 		case Spells::SCUTTLE_BOAT:
 			if(objAtTile && objAtTile->ID == Obj::BOAT)
-				CCS->curh->changeGraphic(0, 42);
+				CCS->curh->changeGraphic(ECursor::ADVENTURE, 42);
 			else
-				CCS->curh->changeGraphic(0, 0);
+				CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 			return;
 		case Spells::DIMENSION_DOOR:
 			{
 				const TerrainTile *t = LOCPLINT->cb->getTile(mapPos, false);
 				int3 hpos = selection->getSightCenter();
 				if((!t  ||  t->isClear(LOCPLINT->cb->getTile(hpos)))   &&   isInScreenRange(hpos, mapPos))
-					CCS->curh->changeGraphic(0, 41);
+					CCS->curh->changeGraphic(ECursor::ADVENTURE, 41);
 				else
-					CCS->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 				return;
 			}
 		}
@@ -1271,14 +1271,14 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
 		if(objAtTile)
 		{
 			if(objAtTile->ID == Obj::TOWN && LOCPLINT->cb->getPlayerRelations(LOCPLINT->playerID, objAtTile->tempOwner))
-				CCS->curh->changeGraphic(0, 3);
+				CCS->curh->changeGraphic(ECursor::ADVENTURE, 3);
 			else if(objAtTile->ID == Obj::HERO && objAtTile->tempOwner == LOCPLINT->playerID)
-				CCS->curh->changeGraphic(0, 2);
+				CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
 			else
-				CCS->curh->changeGraphic(0, 0);
+				CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 		}
 		else
-			CCS->curh->changeGraphic(0, 0);
+			CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 	}
 	else if(const CGHeroInstance *h = curHero())
 	{
@@ -1291,18 +1291,18 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
 				if(!LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, objAtTile->tempOwner)) //enemy hero
 				{
 					if(accessible)
-						CCS->curh->changeGraphic(0, 5 + turns*6);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
 					else
-						CCS->curh->changeGraphic(0, 0);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 				}
 				else //our or ally hero
 				{
 					if(selection == objAtTile)
-						CCS->curh->changeGraphic(0, 2);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
 					else if(accessible)
-						CCS->curh->changeGraphic(0, 8 + turns*6);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 8 + turns*6);
 					else
-						CCS->curh->changeGraphic(0, 2);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 2);
 				}
 			}
 			else if(objAtTile->ID == Obj::TOWN)
@@ -1315,30 +1315,30 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
 
 						// Show movement cursor for unguarded enemy towns, otherwise attack cursor.
 						if (townObj && !townObj->armedGarrison())
-							CCS->curh->changeGraphic(0, 9 + turns*6);
+							CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
 						else
-							CCS->curh->changeGraphic(0, 5 + turns*6);
+							CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
 
 					}
 					else
 					{
-						CCS->curh->changeGraphic(0, 0);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 					}
 				}
 				else //our or ally town
 				{
 					if(accessible)
-						CCS->curh->changeGraphic(0, 9 + turns*6);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
 					else
-						CCS->curh->changeGraphic(0, 3);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 3);
 				}
 			}
 			else if(objAtTile->ID == Obj::BOAT)
 			{
 				if(accessible)
-					CCS->curh->changeGraphic(0, 6 + turns*6);
+					CCS->curh->changeGraphic(ECursor::ADVENTURE, 6 + turns*6);
 				else
-					CCS->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 			}
 			else if (objAtTile->ID == Obj::GARRISON || objAtTile->ID == Obj::GARRISON2)
 			{
@@ -1349,28 +1349,28 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
 					// Show battle cursor for guarded enemy garrisons, otherwise movement cursor.
 					if (garrObj  &&  garrObj->stacksCount()
 						&& !LOCPLINT->cb->getPlayerRelations( LOCPLINT->playerID, garrObj->tempOwner) )
-						CCS->curh->changeGraphic(0, 5 + turns*6);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
 					else
-						CCS->curh->changeGraphic(0, 9 + turns*6);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
 				}
 				else
-					CCS->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 			}
 			else if (guardingCreature && accessible) //(objAtTile->ID == 54) //monster
 			{
-				CCS->curh->changeGraphic(0, 5 + turns*6);
+				CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
 			}
 			else
 			{
 				if(accessible)
 				{
 					if(pnode->land)
-						CCS->curh->changeGraphic(0, 9 + turns*6);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 9 + turns*6);
 					else
-						CCS->curh->changeGraphic(0, 28 + turns);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 28 + turns);
 				}
 				else
-					CCS->curh->changeGraphic(0, 0);
+					CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 			}
 		}
 		else //no objs
@@ -1379,29 +1379,29 @@ void CAdvMapInt::tileHovered(const int3 &mapPos)
 			{
 				if (guardingCreature)
 				{
-					CCS->curh->changeGraphic(0, 5 + turns*6);
+					CCS->curh->changeGraphic(ECursor::ADVENTURE, 5 + turns*6);
 				} 
 				else
 				{
 					if(pnode->land)
 					{
                         if(LOCPLINT->cb->getTile(h->getPosition(false))->terType != ETerrainType::WATER)
-							CCS->curh->changeGraphic(0, 4 + turns*6);
+							CCS->curh->changeGraphic(ECursor::ADVENTURE, 4 + turns*6);
 						else
-							CCS->curh->changeGraphic(0, 7 + turns*6); //anchor
+							CCS->curh->changeGraphic(ECursor::ADVENTURE, 7 + turns*6); //anchor
 					}
 					else
-						CCS->curh->changeGraphic(0, 6 + turns*6);
+						CCS->curh->changeGraphic(ECursor::ADVENTURE, 6 + turns*6);
 				}
 			}
 			else
-				CCS->curh->changeGraphic(0, 0);
+				CCS->curh->changeGraphic(ECursor::ADVENTURE, 0);
 		}
 	}
 
 	if(ourInaccessibleShipyard(objAtTile))
 	{
-		CCS->curh->changeGraphic(0, 6);
+		CCS->curh->changeGraphic(ECursor::ADVENTURE, 6);
 	}
 }
 
@@ -1480,7 +1480,7 @@ const IShipyard * CAdvMapInt::ourInaccessibleShipyard(const CGObjectInstance *ob
 {
 	const IShipyard *ret = IShipyard::castFrom(obj);
 
-	if(!ret || obj->tempOwner != player || CCS->curh->mode || (CCS->curh->number != 6 && CCS->curh->number != 0))
+	if(!ret || obj->tempOwner != player || CCS->curh->type || (CCS->curh->frame != 6 && CCS->curh->frame != 0))
 		return NULL;
 
 	return ret;

+ 2 - 2
client/CCreatureWindow.cpp

@@ -624,9 +624,9 @@ void CCreatureWindow::setArt(const CArtifactInstance *art)
 	if (creatureArtifact)
 	{
 		if (artifactImage == NULL)
-			artifactImage = new CAnimImage("ARTIFACT", creatureArtifact->artType->id, 0, 466, 100);
+			artifactImage = new CAnimImage("ARTIFACT", creatureArtifact->artType->iconIndex, 0, 466, 100);
 		else
-			artifactImage->setFrame(creatureArtifact->artType->id);
+			artifactImage->setFrame(creatureArtifact->artType->iconIndex);
 	}
 	else
 		artifactImage = NULL;

+ 2 - 2
client/CPlayerInterface.cpp

@@ -1569,9 +1569,9 @@ void CPlayerInterface::update()
 		GH.drawFPSCounter();
 
 	// draw the mouse cursor and update the screen
-	CCS->curh->draw1();
+	CCS->curh->drawWithScreenRestore();
 	CSDL_Ext::update(screen);
-	CCS->curh->draw2();
+	CCS->curh->drawRestored();
 }
 
 int CPlayerInterface::getLastIndex( std::string namePrefix)

+ 4 - 4
client/CPreGame.cpp

@@ -511,9 +511,9 @@ void CGPreGame::update()
 		GH.drawFPSCounter();
 
 	// draw the mouse cursor and update the screen
-	CCS->curh->draw1();
+	CCS->curh->drawWithScreenRestore();
 	CSDL_Ext::update(screen);
-	CCS->curh->draw2();
+	CCS->curh->drawRestored();
 }
 
 void CGPreGame::openCampaignScreen(std::string name)
@@ -808,7 +808,7 @@ void CSelectionScreen::changeSelection(const CMapInfo * to)
 			}
 			else
 			{
-				sInfo.mapGenOptions = nullptr;
+				sInfo.mapGenOptions.reset();
 			}
 		}
 	}
@@ -2812,7 +2812,7 @@ OptionsTab::CPregameTooltipBox::CPregameTooltipBox(CPlayerSettingsHelper & helpe
 {
 	OBJ_CONSTRUCTION_CAPTURING_ALL;
 
-	int value;
+	int value = PlayerSettings::NONE;
 
 	switch(CPlayerSettingsHelper::type)
 	{

+ 97 - 47
client/GUIClasses.cpp

@@ -203,9 +203,9 @@ CTownTooltip::CTownTooltip(Point pos, const CGTownInstance * town):
 void CGarrisonSlot::setHighlight(bool on)
 {
 	if (on)
-		selectionImage->recActions |= UPDATE | SHOWALL; //show
+		selectionImage->enable(); //show
 	else
-		selectionImage->recActions &= ~(UPDATE | SHOWALL); //hide
+		selectionImage->disable(); //hide
 }
 
 void CGarrisonSlot::hover (bool on)
@@ -459,16 +459,16 @@ void CGarrisonSlot::update()
 
 	if (creature)
 	{
-		creatureImage->recActions |= (UPDATE | SHOWALL);
+		creatureImage->enable();
 		creatureImage->setFrame(creature->iconIndex);
 
-		stackCount->recActions |= (UPDATE | SHOWALL);
+		stackCount->enable();
 		stackCount->setTxt(boost::lexical_cast<std::string>(myStack->count));
 	}
 	else
 	{
-		creatureImage->recActions &= ~(UPDATE | SHOWALL);
-		stackCount->recActions &= ~(UPDATE | SHOWALL);
+		creatureImage->disable();
+		stackCount->disable();
 	}
 }
 
@@ -489,10 +489,10 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg
 
 	creatureImage = new CAnimImage(imgName, creature ? creature->iconIndex : 0);
 	if (!creature)
-		creatureImage->recActions &= ~(UPDATE | SHOWALL);
+		creatureImage->disable();
 
 	selectionImage = new CAnimImage(imgName, 1);
-	selectionImage->recActions &= ~(UPDATE | SHOWALL); //hide it
+	selectionImage->disable();
 
 	if(Owner->smallIcons)
 	{
@@ -507,7 +507,7 @@ CGarrisonSlot::CGarrisonSlot(CGarrisonInt *Owner, int x, int y, int IID, int Upg
 
 	stackCount = new CLabel(pos.w, pos.h, owner->smallIcons ? FONT_TINY : FONT_MEDIUM, BOTTOMRIGHT, Colors::WHITE);
 	if (!creature)
-		stackCount->recActions &= ~(UPDATE | SHOWALL);
+		stackCount->disable();
 	else
 		stackCount->setTxt(boost::lexical_cast<std::string>(myStack->count));
 }
@@ -937,7 +937,7 @@ size_t CComponent::getIndex()
 	case secskill:   return subtype*3 + 3 + val - 1;
 	case resource:   return subtype;
 	case creature:   return CGI->creh->creatures[subtype]->iconIndex;
-	case artifact:   return subtype;
+	case artifact:   return CGI->arth->artifacts[subtype]->iconIndex;
 	case experience: return 4;
 	case spell:      return subtype;
 	case morale:     return val+3;
@@ -2005,7 +2005,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
 				aw->arts->markPossibleSlots(art);
 
 				//aw->arts->commonInfo->dst.AOH = aw->arts;
-				CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[art->artType->id].bitmap);
+				CCS->curh->dragAndDropCursor(new CAnimImage("artifact", art->artType->iconIndex));
 
 				aw->arts->artifactsOnAltar.erase(art);
 				id = -1;
@@ -3964,16 +3964,67 @@ void CWindowWithGarrison::updateGarrisons()
 	garr->recreateSlots();
 }
 
-CArtPlace::CArtPlace(const CArtifactInstance* Art)
-	:picked(false), marked(false), locked(false), ourArt(Art)
-{
-}
-
 CArtPlace::CArtPlace(Point position, const CArtifactInstance * Art):
-	picked(false), marked(false), locked(false), ourArt(Art)
+    locked(false), picked(false), marked(false), ourArt(Art)
 {
 	pos += position;
 	pos.w = pos.h = 44;
+	createImage();
+}
+
+void CArtPlace::createImage()
+{
+	OBJ_CONSTRUCTION_CAPTURING_ALL;
+
+	int graphic = 0;
+	if (ourArt)
+		graphic = ourArt->artType->iconIndex;
+	if (locked)
+		graphic = GameConstants::ID_LOCK;
+
+	image = new CAnimImage("artifact", graphic);
+	if (!ourArt)
+		image->disable();
+
+	selection = new CAnimImage("artifact", GameConstants::ID_SELECTION);
+	selection->disable();
+}
+
+void CArtPlace::lockSlot(bool on)
+{
+	if (locked == on)
+		return;
+
+	locked = on;
+
+	if (on)
+		image->setFrame(GameConstants::ID_LOCK);
+	else
+		image->setFrame(ourArt->artType->iconIndex);
+}
+
+void CArtPlace::pickSlot(bool on)
+{
+	if (picked == on)
+		return;
+
+	picked = on;
+	if (on)
+		image->disable();
+	else
+		image->enable();
+}
+
+void CArtPlace::selectSlot(bool on)
+{
+	if (marked == on)
+		return;
+
+	marked = on;
+	if (on)
+		selection->enable();
+	else
+		selection->disable();
 }
 
 void CArtPlace::clickLeft(tribool down, bool previousState)
@@ -3994,7 +4045,7 @@ void CArtPlace::clickLeft(tribool down, bool previousState)
 			else
 			{
 				ourOwner->unmarkSlots(false);
-				marked = true;
+				selectSlot(true);
 				ourOwner->highlightModeCallback(this);
 			}
 		}
@@ -4150,19 +4201,20 @@ void CArtPlace::select ()
 	if (locked)
 		return;
 
-	picked = true;
+	selectSlot(true);
+	pickSlot(true);
 	if(ourArt->canBeDisassembled() && slotID < GameConstants::BACKPACK_START) //worn combined artifact -> locks have to disappear
 	{
 		for(int i = 0; i < GameConstants::BACKPACK_START; i++)
 		{
 			CArtPlace *ap = ourOwner->getArtPlace(i);
-			ap->picked = ourArt->isPart(ap->ourArt);
+			ap->pickSlot(ourArt->isPart(ap->ourArt));
 		}
 	}
 
 	//int backpackCorrection = -(slotID - Arts::BACKPACK_START < ourOwner->backpackPos);
 
-	CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[ourArt->artType->id].bitmap);
+	CCS->curh->dragAndDropCursor(new CAnimImage("artifact", ourArt->artType->iconIndex));
 	ourOwner->commonInfo->src.setTo(this, false);
 	ourOwner->markPossibleSlots(ourArt);
 
@@ -4178,11 +4230,11 @@ void CArtPlace::select ()
  */
 void CArtPlace::deselect ()
 {
-	picked = false;
+	pickSlot(false);
 	if(ourArt && ourArt->canBeDisassembled()) //combined art returned to its slot -> restore locks
 	{
 		for(int i = 0; i < GameConstants::BACKPACK_START; i++)
-			ourOwner->getArtPlace(i)->picked = false;
+			ourOwner->getArtPlace(i)->pickSlot(false);
 	}
 
 	CCS->curh->dragAndDropCursor(NULL);
@@ -4200,8 +4252,7 @@ void CArtPlace::showAll(SDL_Surface * to)
 {
 	if (ourArt && !picked && ourArt == ourOwner->curHero->getArt(slotID, false)) //last condition is needed for disassembling -> artifact may be gone, but we don't know yet TODO: real, nice solution
 	{
-		int graphic = locked ? GameConstants::ID_LOCK : ourArt->artType->id;
-		blitAt(graphics->artDefs->ourImages[graphic].bitmap, pos.x, pos.y, to);
+		CIntObject::showAll(to);
 	}
 
 	if(marked && active)
@@ -4246,11 +4297,14 @@ void CArtPlace::setArtifact(const CArtifactInstance *art)
 	ourArt = art;
 	if(!art)
 	{
+		image->disable();
 		text = std::string();
 		hoverText = CGI->generaltexth->allTexts[507];
 	}
 	else
 	{
+		image->enable();
+		image->setFrame(locked ? GameConstants::ID_LOCK : art->artType->iconIndex);
 		text = ourArt->artType->Description();
 		if(art->artType->id == 1) //spell scroll
 		{
@@ -4529,7 +4583,7 @@ void CArtifactsOfHero::markPossibleSlots(const CArtifactInstance* art)
 {
 	BOOST_FOREACH(CArtifactsOfHero *aoh, commonInfo->participants)
 		BOOST_FOREACH(CArtPlace *place, aoh->artWorn)
-			place->marked = art->canBePutAt(ArtifactLocation(aoh->curHero, place->slotID), true);
+			place->selectSlot(art->canBePutAt(ArtifactLocation(aoh->curHero, place->slotID), true));
 
 	safeRedraw();
 }
@@ -4552,9 +4606,9 @@ void CArtifactsOfHero::unmarkSlots(bool withRedraw /*= true*/)
 void CArtifactsOfHero::unmarkLocalSlots(bool withRedraw /*= true*/)
 {
 	BOOST_FOREACH(CArtPlace *place, artWorn)
-		place->marked = false;
+		place->selectSlot(false);
 	BOOST_FOREACH(CArtPlace *place, backpack)
-		place->marked = false;
+		place->selectSlot(false);
 
 	if(withRedraw)
 		safeRedraw();
@@ -4570,13 +4624,13 @@ void CArtifactsOfHero::setSlotData(CArtPlace* artPlace, int slotID)
 		return;
 	}
 
-	artPlace->picked = false;
+	artPlace->pickSlot(false);
 	artPlace->slotID = slotID;
 
 	if(const ArtSlotInfo *asi = curHero->getSlot(slotID))
 	{
 		artPlace->setArtifact(asi->artifact);
-		artPlace->locked = asi->locked;
+		artPlace->lockSlot(asi->locked);
 	}
 	else
 		artPlace->setArtifact(NULL);
@@ -4587,7 +4641,7 @@ void CArtifactsOfHero::setSlotData(CArtPlace* artPlace, int slotID)
  */
 void CArtifactsOfHero::eraseSlotData (CArtPlace* artPlace, int slotID)
 {
-	artPlace->picked = false;
+	artPlace->pickSlot(false);
 	artPlace->slotID = slotID;
 	artPlace->setArtifact(NULL);
 }
@@ -4638,20 +4692,19 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart
 	pos += position;
 	artWorn.resize(19);
 
-	std::vector<Rect> slotPos;
-	slotPos += genRect(44,44,509,30), genRect(44,44,567,240), genRect(44,44,509,80),
-		genRect(44,44,383,68), genRect(44,44,564,183), genRect(44,44,509,130),
-		genRect(44,44,431,68), genRect(44,44,610,183), genRect(44,44,515,295),
-		genRect(44,44,383,143), genRect(44,44,399,194), genRect(44,44,415,245),
-		genRect(44,44,431,296), genRect(44,44,564,30), genRect(44,44,610,30),
-		genRect(44,44,610,76), genRect(44,44,610,122), genRect(44,44,610,310),
-		genRect(44,44,381,296);
+	std::vector<Point> slotPos;
+	slotPos += Point(509,30),  Point(567,240), Point(509,80),
+	           Point(383,68),  Point(564,183), Point(509,130),
+	           Point(431,68),  Point(610,183), Point(515,295),
+	           Point(383,143), Point(399,194), Point(415,245),
+	           Point(431,296), Point(564,30),  Point(610,30),
+	           Point(610,76),  Point(610,122), Point(610,310),
+	           Point(381,296);
 
 	// Create slots for worn artifacts.
 	for (size_t g = 0; g < 19 ; g++)
 	{
-		artWorn[g] = new CArtPlace(NULL);
-		artWorn[g]->pos = slotPos[g] + pos;
+		artWorn[g] = new CArtPlace(slotPos[g]);
 		artWorn[g]->ourOwner = this;
 		eraseSlotData(artWorn[g], g);
 	}
@@ -4659,12 +4712,9 @@ CArtifactsOfHero::CArtifactsOfHero(const Point& position, bool createCommonPart
 	// Create slots for the backpack.
 	for(size_t s=0; s<5; ++s)
 	{
-		CArtPlace * add = new CArtPlace(NULL);
+		CArtPlace * add = new CArtPlace(Point(403 + 46 * s, 365));
 
 		add->ourOwner = this;
-		add->pos.x = pos.x + 403 + 46*s;
-		add->pos.y = pos.y + 365;
-		add->pos.h = add->pos.w = 44;
 		eraseSlotData(add, 19 + s);
 
 		backpack.push_back(add);
@@ -4782,7 +4832,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
 			commonInfo->src.art = dst.getArt();
 			commonInfo->src.slotID = dst.slot;
 			assert(commonInfo->src.AOH);
-			CCS->curh->dragAndDropCursor(graphics->artDefs->ourImages[dst.getArt()->artType->id].bitmap);
+			CCS->curh->dragAndDropCursor(new CAnimImage("artifact", dst.getArt()->artType->iconIndex));
 			markPossibleSlots(dst.getArt());
 		}
 	}
@@ -5272,7 +5322,7 @@ int CUniversityWindow::CItem::state()
 		return 1;
 	if (parent->hero->secSkills.size() >= GameConstants::SKILL_PER_HERO)//can't learn more skills
 		return 0;
-	if (parent->hero->type->heroClass->proSec[ID]==0)//can't learn this skill (like necromancy for most of non-necros)
+	if (parent->hero->type->heroClass->secSkillProbability[ID]==0)//can't learn this skill (like necromancy for most of non-necros)
 		return 0;
 	return 2;
 }

+ 15 - 5
client/GUIClasses.h

@@ -881,16 +881,26 @@ public:
 /// Artifacts can be placed there. Gets shown at the hero window
 class CArtPlace: public LRClickableAreaWTextComp
 {
-public:
-	int slotID; //Arts::EPOS enum + backpack starting from Arts::BACKPACK_START
+	CAnimImage *image;
+	CAnimImage *selection;
 
+	void createImage();
+
+public:
+	// consider these members as const - change them only with appropriate methods e.g. lockSlot()
+	bool locked;
 	bool picked;
 	bool marked;
-	bool locked;
+
+	int slotID; //Arts::EPOS enum + backpack starting from Arts::BACKPACK_START
+
+	void lockSlot(bool on);
+	void pickSlot(bool on);
+	void selectSlot(bool on);
+
 	CArtifactsOfHero * ourOwner;
-	const CArtifactInstance * ourArt;
+	const CArtifactInstance * ourArt; // should be changed only with setArtifact()
 
-	CArtPlace(const CArtifactInstance * Art); //c-tor
 	CArtPlace(Point position, const CArtifactInstance * Art = NULL); //c-tor
 	void clickLeft(tribool down, bool previousState);
 	void clickRight(tribool down, bool previousState);

+ 0 - 1
client/Graphics.cpp

@@ -142,7 +142,6 @@ Graphics::Graphics()
 	tasks += GET_DEF_ESS(resources32,"RESOURCE.DEF");
 	tasks += GET_DEF(smi2,"TWCRPORT.DEF");
 	tasks += GET_DEF_ESS(flags,"CREST58.DEF");
-	tasks += GET_DEF_ESS(abils82,"SECSK82.DEF");
 	tasks += GET_DEF_ESS(spellscr,"SPELLSCR.DEF");
 	tasks += GET_DEF_ESS(heroMoveArrows,"ADAG.DEF");
 

+ 0 - 2
client/Graphics.h

@@ -66,8 +66,6 @@ public:
 	std::vector< std::string > battleHeroes; //battleHeroes[hero type] - name of def that has hero animation for battle
 	std::map< int, std::vector < std::string > > battleACToDef; //maps AC format to vector of appropriate def names
 	CDefEssential * spellEffectsPics; //bitmaps representing spells affecting a stack in battle
-	//abilities
-	CDefEssential * abils82;
 	//spells
 	CDefEssential *spellscr; //spell on the scroll 83x61
 	//functions

+ 68 - 53
client/UIFramework/CCursorHandler.cpp

@@ -3,8 +3,8 @@
 
 #include <SDL.h>
 #include "SDL_Extensions.h"
-#include "../CGameInfo.h"
-#include "../CDefHandler.h"
+#include "CAnimation.h"
+#include "UIFramework/CGuiHandler.h"
 
 /*
  * CCursorHandler.cpp, part of VCMI engine
@@ -20,31 +20,44 @@ extern SDL_Surface * screen;
 
 void CCursorHandler::initCursor()
 {
-	mode = number = xpos = ypos = 0;
-	dndImage = NULL;
+	xpos = ypos = 0;
+	type = ECursor::DEFAULT;
+	dndObject = nullptr;
+
 	help = CSDL_Ext::newSurface(40,40);
-	cursors.push_back(CDefHandler::giveDef("CRADVNTR.DEF"));
-	cursors.push_back(CDefHandler::giveDef("CRCOMBAT.DEF"));
-	cursors.push_back(CDefHandler::giveDef("CRDEFLT.DEF"));
-	cursors.push_back(CDefHandler::giveDef("CRSPELL.DEF"));
 	SDL_ShowCursor(SDL_DISABLE);
+
+	changeGraphic(ECursor::ADVENTURE, 0);
 }
 
-void CCursorHandler::changeGraphic(const int & type, const int & no)
+void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index)
 {
-	mode = type;
-	number = no;
+	std::string cursorDefs[4] = { "CRADVNTR.DEF", "CRCOMBAT.DEF", "CRDEFLT.DEF", "CRSPELL.DEF" };
+
+	if (type != this->type)
+	{
+		BLOCK_CAPTURING; // not used here
+
+		this->type = type;
+		this->frame = index;
+
+		delete currentCursor;
+		currentCursor = new CAnimImage(cursorDefs[int(type)], index);
+	}
+
+	if (frame != index)
+	{
+		frame = index;
+		currentCursor->setFrame(index);
+	}
 }
 
-/**
- * Replaces the cursor with a custom image.
- *
- * @param image Image to replace cursor with or NULL to use the normal
- * cursor.
- */
-void CCursorHandler::dragAndDropCursor(SDL_Surface* image)
+void CCursorHandler::dragAndDropCursor(CAnimImage * object)
 {
-	dndImage = image;
+	if (dndObject)
+		delete dndObject;
+
+	dndObject = object;
 }
 
 void CCursorHandler::cursorMove(const int & x, const int & y)
@@ -52,31 +65,34 @@ void CCursorHandler::cursorMove(const int & x, const int & y)
 	xpos = x;
 	ypos = y;
 }
-void CCursorHandler::draw1()
+
+void CCursorHandler::drawWithScreenRestore()
 {
-	if(!Show) return;
+	if(!showing) return;
 	int x = xpos, y = ypos;
 	shiftPos(x, y);
 
 	SDL_Rect temp_rect1 = genRect(40,40,x,y);
 	SDL_Rect temp_rect2 = genRect(40,40,0,0);
 	SDL_BlitSurface(screen, &temp_rect1, help, &temp_rect2);
-// 	if (dndImage)
-// 		blitAt(dndImage, x - dndImage->w/2, y - dndImage->h/2);
-// 	else
-// 		blitAt(cursors[mode]->ourImages[number].bitmap,x,y);
-
-	if (dndImage) {
-		SDL_Rect temp_rect =genRect(40, 40, x - dndImage->w/2, y - dndImage->h/2);
-			SDL_BlitSurface(dndImage, NULL, screen, &temp_rect);
-	} else {
-		SDL_Rect temp_rect = genRect(40,40,x,y);
-			SDL_BlitSurface(cursors[mode]->ourImages[number].bitmap, NULL, screen, &temp_rect);
+
+	if (dndObject)
+	{
+		dndObject->moveTo(Point(x - dndObject->pos.w/2, y - dndObject->pos.h/2));
+		dndObject->showAll(screen);
+	}
+	else
+	{
+		currentCursor->moveTo(Point(x,y));
+		currentCursor->showAll(screen);
 	}
 }
-void CCursorHandler::draw2()
+
+void CCursorHandler::drawRestored()
 {
-	if(!Show) return;
+	if(!showing)
+		return;
+
 	int x = xpos, y = ypos;
 	shiftPos(x, y);
 
@@ -87,21 +103,21 @@ void CCursorHandler::draw2()
 
 void CCursorHandler::draw(SDL_Surface *to)
 {
-	SDL_Rect temp_rect = genRect(40, 40, xpos, ypos);
-	CSDL_Ext::blitSurface(cursors[mode]->ourImages[number].bitmap, 0, to, &temp_rect);
+	currentCursor->moveTo(Point(xpos, ypos));
+	currentCursor->showAll(screen);
 }
 
 void CCursorHandler::shiftPos( int &x, int &y )
 {
-	if((mode==1 && number!=6) || mode ==3)
+	if(( type == ECursor::COMBAT && frame != ECursor::COMBAT_POINTER) || type == ECursor::SPELLBOOK)
 	{
 		x-=16;
 		y-=16;
 
 		// Properly align the melee attack cursors.
-		if (mode == 1) 
+		if (type == ECursor::COMBAT == 1)
 		{
-			switch (number) 
+			switch (frame)
 			{
 			case 7: // Bottom left
 				x -= 6;
@@ -138,22 +154,22 @@ void CCursorHandler::shiftPos( int &x, int &y )
 			}
 		}
 	}
-	else if(mode==0)
+	else if(ECursor::ADVENTURE == 0)
 	{
-		if(number == 0); //to exclude
-		else if(number == 2)
+		if (frame == 0); //to exclude
+		else if(frame == 2)
 		{
 			x -= 12;
 			y -= 10;
 		}
-		else if(number == 3)
+		else if(frame == 3)
 		{
 			x -= 12;
 			y -= 12;
 		}
-		else if(number < 27)
+		else if(frame < 27)
 		{
-			int hlpNum = (number - 4)%6;
+			int hlpNum = (frame - 4)%6;
 			if(hlpNum == 0)
 			{
 				x -= 15;
@@ -185,12 +201,12 @@ void CCursorHandler::shiftPos( int &x, int &y )
 				y -= 16;
 			}
 		}
-		else if(number == 41)
+		else if(frame == 41)
 		{
 			x -= 14;
 			y -= 16;
 		}
-		else if(number < 31 || number == 42)
+		else if(frame < 31 || frame == 42)
 		{
 			x -= 20;
 			y -= 20;
@@ -200,10 +216,9 @@ void CCursorHandler::shiftPos( int &x, int &y )
 
 void CCursorHandler::centerCursor()
 {
-	SDL_Surface *cursor = this->cursors[mode]->ourImages[number].bitmap;
-	this->xpos = (screen->w / 2.) - (cursor->w / 2.);
-	this->ypos = (screen->h / 2.) - (cursor->h / 2.);
-	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);	
+	this->xpos = (screen->w / 2.) - (currentCursor->pos.w / 2.);
+	this->ypos = (screen->h / 2.) - (currentCursor->pos.h / 2.);
+	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE);
 	SDL_WarpMouse(this->xpos, this->ypos);
 	SDL_EventState(SDL_MOUSEMOTION, SDL_ENABLE);
 }
@@ -213,6 +228,6 @@ CCursorHandler::~CCursorHandler()
 	if(help)
 		SDL_FreeSurface(help);
 
-	for(int g=0; g<cursors.size(); ++g)
-		delete cursors[g];
+	delete currentCursor;
+	delete dndObject;
 }

+ 39 - 19
client/UIFramework/CCursorHandler.h

@@ -1,9 +1,6 @@
 #pragma once
 
-
-
-struct SDL_Thread;
-class CDefHandler;
+class CAnimImage;
 struct SDL_Surface;
 
 /*
@@ -30,25 +27,48 @@ namespace ECursor
 /// handles mouse cursor
 class CCursorHandler 
 {
-public:
-	int mode, number;
 	SDL_Surface * help;
-	SDL_Surface * dndImage;
-	bool Show;
-
-	std::vector<CDefHandler*> cursors;
-	int xpos, ypos; //position of cursor
-	void initCursor(); //inits cursorHandler - run only once, it's not memleak-proof (rev 1333)
-	void cursorMove(const int & x, const int & y); //change cursor's positions to (x, y)
-	void changeGraphic(const int & type, const int & no); //changes cursor graphic for type type (0 - adventure, 1 - combat, 2 - default, 3 - spellbook) and frame no (not used for type 3)
-	void dragAndDropCursor (SDL_Surface* image); // Replace cursor with a custom image.
-	void draw1();
+	CAnimImage * currentCursor;
+	CAnimImage * dndObject; //if set, overrides currentCursor
+	bool showing;
+
+public:
+	/// position of cursor
+	int xpos, ypos;
+
+	/// Current cursor
+	ECursor::ECursorTypes type;
+	size_t frame;
+
+	/// inits cursorHandler - run only once, it's not memleak-proof (rev 1333)
+	void initCursor();
+
+	/// changes cursor graphic for type type (0 - adventure, 1 - combat, 2 - default, 3 - spellbook) and frame index (not used for type 3)
+	void changeGraphic(ECursor::ECursorTypes type, int index);
+
+	/**
+	 * Replaces the cursor with a custom image.
+	 *
+	 * @param image Image to replace cursor with or NULL to use the normal
+	 * cursor. CursorHandler takes ownership of object
+	 */
+	void dragAndDropCursor (CAnimImage * image);
+
+	/// Draw cursor preserving original image below cursor
+	void drawWithScreenRestore();
+	/// Restore original image below cursor
+	void drawRestored();
+	/// Simple draw cursor
 	void draw(SDL_Surface *to);
 
 	void shiftPos( int &x, int &y );
-	void draw2();
-	void hide() { Show=0; };
-	void show() { Show=1; };
+	void hide() { showing=0; };
+	void show() { showing=1; };
+
+	/// change cursor's positions to (x, y)
+	void cursorMove(const int & x, const int & y);
+	/// Move cursor to screen center
 	void centerCursor();
+
 	~CCursorHandler();
 };

+ 1 - 1
client/mapHandler.cpp

@@ -568,7 +568,7 @@ void CMapHandler::terrainRect( int3 top_tile, ui8 anim, const std::vector< std::
 						//pick graphics of hero (or boat if hero is sailing)
 						iv = (themp->boat) 
 							? &graphics->boatAnims[themp->boat->subID]->ourImages
-							: &graphics->heroAnims[themp->type->heroType]->ourImages;
+							: &graphics->heroAnims[themp->type->heroClass->id]->ourImages;
 
 						//pick appropriate flag set
 						if(themp->boat)

+ 2277 - 1032
config/heroes.json

@@ -1,1036 +1,2281 @@
 {
 	// heroes' information.
-	//   id: hero id
-	//   female: true if hero is female, else false
-	//   skill_set: initial set of secondary abilities (skill ID, initial skill level)
-	//   spell: hero starts with that initial spell
-	"heroes": [
-		{ "id": 0,
-		  "class" : 0,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 1, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 1, "info": 0 } ] },
-		{ "id": 1,
-		  "class" : 0,
-		  "female": true,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 1, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 2 } ] },
-		{ "id": 2,
-		  "class" : 0,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 23, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 4 } ] },
-		{ "id": 3,
-		  "class" : 0,
-		  "female": true,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 5, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 2, "subtype": 5, "info": 1 } ] },
-		{ "id": 4,
-		  "class" : 0,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 13, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 13, "info": 0 } ] },
-		{ "id": 5,
-		  "class" : 0,
-		  "female": true,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 6 } ] },
-		{ "id": 6,
-		  "class" : 0,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 20, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 146 } ] },
-		{ "id": 7,
-		  "class" : 0,
-		  "female": true,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 10 } ] },
-		{ "id": 8,
-		  "class" : 1,
-		  "female": false,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 27, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 27, "info": 0 } ] },
-		{ "id": 9,
-		  "class" : 1,
-		  "female": true,
-		  "spell": 41,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 4, "level": 1 } ],
-		  "specialties": [ { "type":6, "val": 3, "subtype": 41, "info": 0 } ] },
-		{ "id": 10,
-		  "class" : 1,
-		  "female": false,
-		  "spell": 45,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 13, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 45, "info": 0 } ] },
-		{ "id": 11,
-		  "class" : 1,
-		  "female": true,
-		  "spell": 20,
-		  "skill_set": [ { "skill": 7, "level": 2 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 20, "info": 0 } ] },
-		{ "id": 12,
-		  "class" : 1,
-		  "female": false,
-		  "spell": 42,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 8, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 8 } ] },
-		{ "id": 13,
-		  "class" : 1,
-		  "female": true,
-		  "spell": 35,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 11, "info": 0 } ] },
-		{ "id": 14,
-		  "class" : 1,
-		  "spell": 48,
-		  "female": false,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 21, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 48, "info": 0 } ] },
-		{ "id": 15,
-		  "class" : 1,
-		  "female": true,
-		  "spell": 37,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 16,
-		  "class" : 2,
-		  "female": true,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 23, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 23, "info": 0 } ] },
-		{ "id": 17,
-		  "class" : 2,
-		  "female": false,
-		  "skill_set": [ { "skill": 9, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 16 } ] },
-		{ "id": 18,
-		  "class" : 2,
-		  "female": true,
-		  "skill_set": [ { "skill": 1, "level": 2 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 19,
-		  "class" : 2,
-		  "female": false,
-		  "skill_set": [ { "skill": 4, "level": 1 },
-		  			    { "skill": 6, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 22 } ] },
-		{ "id": 20,
-		  "class" : 2,
-		  "female": false,
-		  "skill_set": [ { "skill": 26, "level": 2 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 26, "info": 0 } ] },
-		{ "id": 21,
-		  "class" : 2,
-		  "female": false,
-		  "skill_set": [ { "skill": 1, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 18 } ] },
-		{ "id": 22,
-		  "class" : 2,
-		  "female": false,
-		  "skill_set": [ { "skill": 0, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 24 } ] },
-		{ "id": 23,
-		  "class" : 2,
-		  "female": true,
-		  "skill_set": [ { "skill": 1, "level": 1 },
-		  			    { "skill": 2, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 2, "info": 0 } ] },
-		{ "id": 24,
-		  "class" : 3,
-		  "spell": 55,
-		  "female": false,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 18, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 55, "info": 1 } ] },
-		{ "id": 25,
-		  "class" : 3,
-		  "female": false,
-		  "spell": 37,
-		  "skill_set": [ { "skill": 7, "level": 2 },
-		  			    { "skill": 10, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 37, "info": 0 } ] },
-		{ "id": 26,
-		  "class" : 3,
-		  "female": false,
-		  "spell": 42,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 24, "info": 0 } ] },
-		{ "id": 27,
-		  "class" : 3,
-		  "female": true,
-		  "spell": 0,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 27, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 27, "info": 0 } ] },
-		{ "id": 28,
-		  "class" : 3,
-		  "female": false,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 11, "info": 0 } ] },
-		{ "id": 29,
-		  "class" : 3,
-		  "spell": 51,
-		  "female": true,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 9, "level": 1 } ],
-		  "specialties": [ { "type":7, "val": 0, "subtype": 51, "info": 0 } ] },
-		{ "id": 30,
-		  "class" : 3,
-		  "female": false,
-		  "spell": 16,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 16, "info": 0 } ] },
-		{ "id": 31,
-		  "class" : 3,
-		  "female": false,
-		  "spell": 30,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 3, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 20 } ] },
-		{ "id": 32,
-		  "class" : 4,
-		  "female": false,
-		  "spell": 27,
-		  "skill_set": [ { "skill": 3, "level": 1 },
-		  			    { "skill": 8, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 30 } ] },
-		{ "id": 33,
-		  "class" : 4,
-		  "female": false,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 18, "level": 2 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 36 } ] },
-		{ "id": 34,
-		  "class" : 4,
-		  "spell": 53,
-		  "female": true,
-		  "skill_set": [ { "skill": 8, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 32 } ] },
-		{ "id": 35,
-		  "class" : 4,
-		  "female": true,
-		  "spell": 27,
-		  "skill_set": [ { "skill": 18, "level": 1 },
-		  			    { "skill": 23, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 23, "info": 0 } ] },
-		{ "id": 36,
-		  "class" : 4,
-		  "female": false,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 8, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 146 } ] },
-		{ "id": 37,
-		  "class" : 4,
-		  "female": false,
-		  "spell": 53,
-		  "skill_set": [ { "skill": 18, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 38 } ] },
-		{ "id": 38,
-		  "class" : 4,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 8, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 1, "subtype": 1, "info": 0 } ] },
-		{ "id": 39,
-		  "class" : 4,
-		  "spell": 15,
-		  "female": true,
-		  "skill_set": [ { "skill": 18, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 36 } ] },
-		{ "id": 40,
-		  "class" : 5,
-		  "female": false,
-		  "spell": 60,
-		  "skill_set": [ { "skill": 7, "level": 2 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 60, "info": 0 } ] },
-		{ "id": 41,
-		  "class" : 5,
-		  "female": false,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 8, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 8, "info": 1 } ] },
-		{ "id": 42,
-		  "class" : 5,
-		  "female": true,
-		  "spell": 35,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 11, "info": 0 } ] },
-		{ "id": 43,
-		  "class" : 5,
-		  "female": true,
-		  "spell": 51,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":7, "val": 0, "subtype": 51, "info": 0 } ] },
-		{ "id": 44,
-		  "class" : 5,
-		  "spell": 27,
-		  "female": false,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 10, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 34 } ] },
-		{ "id": 45,
-		  "class" : 5,
-		  "female": false,
-		  "spell": 19,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 19, "info": 0 } ] },
-		{ "id": 46,
-		  "class" : 5,
-		  "female": true,
-		  "spell": 53,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 4, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 53, "info": 0 } ] },
-		{ "id": 47,
-		  "class" : 5,
-		  "female": true,
-		  "spell": 42,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 18, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 48,
-		  "class" : 6,
-		  "female": true,
-		  "skill_set": [ { "skill": 3, "level": 2 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 46 } ] },
-		{ "id": 49,
-		  "class" : 6,
-		  "female": false,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 18, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 52 } ] },
-		{ "id": 50,
-		  "class" : 6,
-		  "female": true,
-		  "skill_set": [ { "skill": 23, "level": 2 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 48 } ] },
-		{ "id": 51,
-		  "class" : 6,
-		  "female": false,
-		  "skill_set": [ { "skill": 19, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 42 } ] },
-		{ "id": 52,
-		  "class" : 6,
-		  "female": true,
-		  "skill_set": [ { "skill": 18, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 53,
-		  "class" : 6,
-		  "female": false,
-		  "skill_set": [ { "skill": 1, "level": 1 },
-		  			    { "skill": 3, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 42 } ] },
-		{ "id": 54,
-		  "class" : 6,
-		  "female": true,
-		  "skill_set": [ { "skill": 20, "level": 1 },
-		  			    { "skill": 2, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 146 } ] },
-		{ "id": 55,
-		  "class" : 6,
-		  "female": true,
-		  "skill_set": [ { "skill": 22, "level": 2 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 50 } ] },
-		{ "id": 56,
-		  "class" : 7,
-		  "spell": 3,
-		  "female": false,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 24, "info": 0 } ] },
-		{ "id": 57,
-		  "class" : 7,
-		  "female": false,
-		  "spell": 22,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 18, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 22, "info": 0 } ] },
-		{ "id": 58,
-		  "class" : 7,
-		  "female": false,
-		  "spell": 30,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 8, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 8, "info": 1 } ] },
-		{ "id": 59,
-		  "class" : 7,
-		  "female": true,
-		  "spell": 45,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 10, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 45, "info": 0 } ] },
-		{ "id": 60,
-		  "class" : 7,
-		  "female": false,
-		  "spell": 53,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 21, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 1, "subtype": 3, "info": 0 } ] },
-		{ "id": 61,
-		  "class" : 7,
-		  "female": true,
-		  "spell": 43,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 43, "info": 0 } ] },
-		{ "id": 62,
-		  "class" : 7,
-		  "female": false,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 25, "info": 0 } ] },
-		{ "id": 63,
-		  "class" : 7,
-		  "female": false,
-		  "spell": 21,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 6, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 21, "info": 0 } ] },
-		{ "id": 64,
-		  "class" : 8,
-		  "female": false,
-		  "spell": 53,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 58 } ] },
-		{ "id": 65,
-		  "class" : 8,
-		  "female": false,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 20, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 62 } ] },
-		{ "id": 66,
-		  "class" : 8,
-		  "female": false,
-		  "spell": 54,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 21, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 64 } ] },
-		{ "id": 67,
-		  "class" : 8,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 60 } ] },
-		{ "id": 68,
-		  "class" : 8,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 66 } ] },
-		{ "id": 69,
-		  "class" : 8,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 12, "level": 2 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 12, "info": 0 } ] },
-		{ "id": 70,
-		  "class" : 8,
-		  "female": false,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 71,
-		  "class" : 8,
-		  "female": false,
-		  "spell": 27,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 23, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 56 } ] },
-		{ "id": 72,
-		  "class" : 9,
-		  "female": true,
-		  "spell": 24,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 18, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 24, "info": 0 } ] },
-		{ "id": 73,
-		  "class" : 9,
-		  "female": true,
-		  "spell": 23,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 7, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 23, "info": 0 } ] },
-		{ "id": 74,
-		  "class" : 9,
-		  "female": false,
-		  "spell": 54,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 25, "info": 0 } ] },
-		{ "id": 75,
-		  "class" : 9,
-		  "female": false,
-		  "spell": 27,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 11, "info": 1 } ] },
-		{ "id": 76,
-		  "class" : 9,
-		  "female": false,
-		  "spell": 39,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 8, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 39, "subtype": 0, "info": 3 } ] },
-		{ "id": 77,
-		  "class" : 9,
-		  "female": true,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 21, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 46, "info": 0 } ] },
-		{ "id": 78,
-		  "class" : 9,
-		  "female": true,
-		  "spell": 42,
-		  "skill_set": [ { "skill": 12, "level": 2 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 12, "info": 0 } ] },
-		{ "id": 79,
-		  "class" : 9,
-		  "female": false,
-		  "spell": 30,
-		  "skill_set": [ { "skill": 12, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 80,
-		  "class" : 10,
-		  "female": true,
-		  "skill_set": [ { "skill": 3, "level": 1 },
-		  			    { "skill": 6, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 72 } ] },
-		{ "id": 81,
-		  "class" : 10,
-		  "female": false,
-		  "skill_set": [ { "skill": 20, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 146 } ] },
-		{ "id": 82,
-		  "class" : 10,
-		  "female": false,
-		  "skill_set": [ { "skill": 19, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 78 } ] },
-		{ "id": 83,
-		  "class" : 10,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 74 } ] },
-		{ "id": 84,
-		  "class" : 10,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 2 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 85,
-		  "class" : 10,
-		  "female": false,
-		  "skill_set": [ { "skill": 2, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 2, "info": 0 } ] },
-		{ "id": 86,
-		  "class" : 10,
-		  "female": true,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 18, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 80 } ] },
-		{ "id": 87,
-		  "class" : 10,
-		  "female": false,
-		  "skill_set": [ { "skill": 19, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 70 } ] },
-		{ "id": 88,
-		  "class" : 11,
-		  "spell": 38,
-		  "female": false,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 18, "level": 1 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 38, "info": 0 } ] },
-		{ "id": 89,
-		  "class" : 11,
-		  "female": false,
-		  "spell": 27,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 8, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 8, "info": 1 } ] },
-		{ "id": 90,
-		  "class" : 11,
-		  "female": false,
-		  "spell": 43,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 25, "info": 0 } ] },
-		{ "id": 91,
-		  "class" : 11,
-		  "female": true,
-		  "spell": 38,
-		  "skill_set": [ { "skill": 7, "level": 2 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 38, "info": 0 } ] },
-		{ "id": 92,
-		  "class" : 11,
-		  "female": false,
-		  "spell": 54,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 11, "info": 1 } ] },
-		{ "id": 93,
-		  "class" : 11,
-		  "female": false,
-		  "spell": 23,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 3, "level": 2 } ],
-		  "specialties": [ { "type":3, "val": 3, "subtype": 23, "info": 0 } ] },
-		{ "id": 94,
-		  "class" : 11,
-		  "female": true,
-		  "spell": 30,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 1, "subtype": 4, "info": 0 } ] },
-		{ "id": 95,
-		  "class" : 11,
-		  "female": false,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 21, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 46, "info": 0 } ] },
-		{ "id": 96,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 1 },
-		  			    { "skill": 10, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 94 } ] },
-		{ "id": 97,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 1 },
-		  			    { "skill": 20, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 146 } ] },
-		{ "id": 98,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 1 },
-		  			    { "skill": 1, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 88 } ] },
-		{ "id": 99,
-		  "class" : 12,
-		  "female": true,
-		  "skill_set": [ { "skill": 22, "level": 1 },
-		  			    { "skill": 3, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 92 } ] },
-		{ "id": 100,
-		  "class" : 12,
-		  "female": true,
-		  "skill_set": [ { "skill": 22, "level": 1 },
-		  			    { "skill": 0, "level": 1 } ] },
-		{ "id": 101,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 84 } ] },
-		{ "id": 102,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 2 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 90 } ] },
-		{ "id": 103,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 22, "info": 0 } ] },
-		{ "id": 104,
-		  "class" : 13,
-		  "spell": 43,
-		  "female": true,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 86 } ] },
-		{ "id": 105,
-		  "class" : 13,
-		  "female": false,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 6, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 25, "info": 0 } ] },
-		{ "id": 106,
-		  "class" : 13,
-		  "female": true,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 2, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 90 } ] },
-		{ "id": 107,
-		  "class" : 13,
-		  "female": false,
-		  "spell": 53,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 2, "info": 0 } ] },
-		{ "id": 108,
-		  "class" : 13,
-		  "female": false,
-		  "spell": 44,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 20, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 53, "info": 0 } ] },
-		{ "id": 109,
-		  "class" : 13,
-		  "spell": 54,
-		  "female": true,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 44, "info": 0 } ] },
-		{ "id": 110,
-		  "class" : 13,
-		  "female": true,
-		  "spell": 30,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 25, "info": 0 } ] },
-		{ "id": 111,
-		  "class" : 13,
-		  "female": false,
-		  "spell": 43,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 11, "info": 1 } ] },
-		{ "id": 112,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 1 },
-		  			    { "skill": 26, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 1, "subtype": 5, "info": 0 } ] },
-		{ "id": 113,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 1 },
-		  			    { "skill": 6, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 106 } ] },
-		{ "id": 114,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 1 },
-		  			    { "skill": 1, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 98 } ] },
-		{ "id": 115,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 2 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 100 } ] },
-		{ "id": 116,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 23, "info": 0 } ] },
-		{ "id": 117,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 1 },
-		  			    { "skill": 0, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 102 } ] },
-		{ "id": 118,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 1 },
-		  			    { "skill": 20, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 104 } ] },
-		{ "id": 119,
-		  "class" : 14,
-		  "female": false,
-		  "skill_set": [ { "skill": 23, "level": 1 },
-		  			    { "skill": 3, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 146 } ] },
-		{ "id": 120,
-		  "class" : 15,
-		  "spell": 45,
-		  "female": true,
-		  "skill_set": [ { "skill": 7, "level": 2 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 108 } ] },
-		{ "id": 121,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 8, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 8, "info": 1 } ] },
-		{ "id": 122,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 54,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 5, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 2, "subtype": 5, "info": 1 } ] },
-		{ "id": 123,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 31,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 27, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 27, "info": 1 } ] },
-		{ "id": 124,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 21, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 46, "info": 0 } ] },
-		{ "id": 125,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 27,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 25, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 25, "info": 0 } ] },
-		{ "id": 126,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 35,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 24, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 24, "info": 0 } ] },
-		{ "id": 127,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 11, "level": 1 } ],
-		  "specialties": [ { "type":2, "val": 5, "subtype": 11, "info": 1 } ] },
-		{ "id": 128,
-		  "class" : 16,
-		  "female": true,
-		  "skill_set": [ { "skill": 20, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":4, "val": 3, "subtype": 1, "info": 120 },
-		  				  { "type":4, "val": 3, "subtype": 2, "info": 120 } ] },
-		{ "id": 129,
-		  "class" : 16,
-		  "female": true,
-		  "skill_set": [ { "skill": 13, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":4, "val": 2, "subtype": 1, "info": 113 },
-		  				  { "type":4, "val": 1, "subtype": 2, "info": 113 },
-						  	 { "type":4, "val": 5, "subtype": 4, "info": 113 } ] },
-		{ "id": 130,
-		  "class" : 16,
-		  "female": true,
-		  "skill_set": [ { "skill": 20, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":4, "val": 1, "subtype": 1, "info": 114 },
-		  				  { "type":4, "val": 2, "subtype": 1, "info": 114 },
-						  	 { "type":4, "val": 2, "subtype": 3, "info": 114 } ] },
-		{ "id": 131,
-		  "class" : 16,
-		  "female": true,
-		  "skill_set": [ { "skill": 19, "level": 2 } ],
-		  "specialties": [ { "type":4, "val": 2, "subtype": 1, "info": 115 } ] },
-		{ "id": 132,
-		  "class" : 16,
-		  "female": false,
-		  "skill_set": [ { "skill": 2, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":4, "val": 3, "subtype": 1, "info": 120 },
-		  				  { "type":4, "val": 3, "subtype": 2, "info": 120 } ] },
-		{ "id": 133,
-		  "class" : 16,
-		  "female": false,
-		  "skill_set": [ { "skill": 13, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":4, "val": 2, "subtype": 1, "info": 113 },
-		  				  { "type":4, "val": 1, "subtype": 2, "info": 113 },
-						  	 { "type":4, "val": 5, "subtype": 4, "info": 113 } ] },
-		{ "id": 134,
-		  "class" : 16,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 2 } ],
-		  "specialties": [ { "type":4, "val": 1, "subtype": 1, "info": 114 },
-		  				  { "type":4, "val": 2, "subtype": 1, "info": 114 },
-						  	 { "type":4, "val": 2, "subtype": 3, "info": 114 } ] },
-		{ "id": 135,
-		  "class" : 16,
-		  "female": false,
-		  "skill_set": [ { "skill": 19, "level": 1 },
-		  			    { "skill": 21, "level": 1 } ],
-		  "specialties": [ { "type":4, "val": 2, "subtype": 1, "info": 115 } ] },
-		{ "id": 136,
-		  "class" : 17,
-		  "spell": 13,
-		  "female": true,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 14, "level": 1 } ],
-		  "specialties": [ { "type":5, "val": 100, "subtype": 13, "info": 0 } ] },
-		{ "id": 137,
-		  "class" : 17,
-		  "female": true,
-		  "spell": 53,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 15, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 53, "info": 0 } ] },
-		{ "id": 138,
-		  "class" : 17,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 16, "level": 1 } ],
-		  "specialties": [ { "type":5, "val": 50, "subtype": 15, "info": 0 } ] },
-		{ "id": 139,
-		  "class" : 17,
-		  "female": true,
-		  "spell": 46,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 17, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 46, "info": 0 } ] },
-		{ "id": 140,
-		  "class" : 17,
-		  "female": false,
-		  "spell": 43,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 14, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 43, "info": 0 } ] },
-		{ "id": 141,
-		  "class" : 17,
-		  "female": false,
-		  "spell": 47,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 15, "level": 1 } ],
-		  "specialties": [ { "type":8, "val": 0, "subtype": 47, "info": 0 } ] },
-		{ "id": 142,
-		  "class" : 17,
-		  "female": false,
-		  "spell": 35,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 16, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 143,
-		  "class" : 17,
-		  "female": false,
-		  "spell": 54,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 17, "level": 1 } ],
-		  "specialties": [ { "type":10, "val": 350, "subtype": 6, "info": 0 } ] },
-		{ "id": 144,
-		  "class" : 0,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 2 } ],
-		  "specialties": [ { "type":12, "val": 2, "subtype": 0, "info": 0 } ] },
-		{ "id": 145,
-		  "class" : 15,
-		  "female": true,
-		  "spell": 22,
-		  "skill_set": [ { "skill": 7, "level": 1 },
-		  			    { "skill": 14, "level": 3 } ],
-		  "specialties": [ { "type":11, "val": 14, "subtype": 0, "info": 0 } ] },
-		{ "id": 146,
-		  "class" : 0,
-		  "female": true,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 4 } ] },
-		{ "id": 147,
-		  "class" : 5,
-		  "female": false,
-		  "spell": 53,
-		  "skill_set": [ { "skill": 7, "level": 2 } ],
-		  "specialties": [ { "type":9, "val": 0, "subtype": 8, "info": 136 },
-		  				  { "type":9, "val": 0, "subtype": 34, "info": 136 } ] },
-		{ "id": 148,
-		  "class" : 2,
-		  "female": false,
-		  "skill_set": [ { "skill": 1, "level": 1 },
-		  			    { "skill": 6, "level": 1 } ],
-		  "specialties": [ { "type":9, "val": 0, "subtype": 2, "info": 137 },
-		  				  { "type":9, "val": 0, "subtype": 18, "info": 137 } ] },
-		{ "id": 149,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 22, "level": 2 } ],
-		  "specialties": [ { "type":4, "val": 5, "subtype": 1, "info": 96 },
-		  				  { "type":4, "val": 5, "subtype": 2, "info": 96 },
-						  	 { "type":4, "val": 10, "subtype": 3, "info": 96 } ] },
-		{ "id": 150,
-		  "class" : 8,
-		  "female": false,
-		  "spell": 54,
-		  "skill_set": [ { "skill": 12, "level": 2 } ],
-		  "specialties": [ { "type":4, "val": 5, "subtype": 1, "info": 66 },
-		  				  { "type":4, "val": 5, "subtype": 2, "info": 66 },
-						  	 { "type":4, "val": 10, "subtype": 3, "info": 66 } ] },
-		{ "id": 151,
-		  "class" : 10,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 13, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":13, "val": 5, "subtype": 1, "info": 0 },
-		  				  { "type":13, "val": 5, "subtype": 2, "info": 0 } ] },
-		{ "id": 152,
-		  "class" : 0,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 23, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 4 } ] },
-		{ "id": 153,
-		  "class" : 10,
-		  "female": true,
-		  "spell": 15,
-		  "skill_set": [ { "skill": 13, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":13, "val": 1, "subtype": 1, "info": 5 },
-		  				  { "type":13, "val": 1, "subtype": 1, "info": 5 } ] },
-		{ "id": 154,
-		  "class" : 12,
-		  "female": false,
-		  "skill_set": [ { "skill": 19, "level": 1 },
-		  			    { "skill": 22, "level": 1 } ],
-		  "specialties": [ { "type":1, "val": 0, "subtype": 0, "info": 90 } ] },
-		{ "id": 155,
-		  "class" : 6,
-		  "female": false,
-		  "skill_set": [ { "skill": 6, "level": 1 },
-		  			    { "skill": 19, "level": 1 } ],
-		  "specialties": [ { "type":4, "val": 4, "subtype": 1, "info": 54 },
-		  				  { "type":4, "val": 2, "subtype": 2, "info": 54 },
-						  	 { "type":4, "val": 1, "subtype": 5, "info": 54 } ] }
+	//	 id: hero id
+	//	 female: true if hero is female, else false
+	//	 skill_set: initial set of secondary abilities (skill ID, initial skill level)
+	//	 spell: hero starts with that initial spell
+	"heroes":
+	[
+		{
+			"id": 0,
+			"class" : "knight",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 1, "level": 1 }
+			],
+		 "specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 1, "info": 0 }
+			]
+		},
+		{
+			"id": 1,
+			"class" : "knight",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 1, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 2 }
+			]
+		},
+		{
+			"id": 2,
+			"class" : "knight",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 23, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 4 }
+			]
+		},
+		{
+			"id": 3,
+			"class" : "knight",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 5, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 2, "subtype": 5, "info": 1 }
+			]
+		},
+		{
+			"id": 4,
+			"class" : "knight",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 13, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 13, "info": 0 }
+			]
+		},
+		{
+			"id": 5,
+			"class" : "knight",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 6 }
+			]
+		},
+		{
+			"id": 6,
+			"class" : "knight",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 20, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 146 }
+			]
+		},
+		{
+			"id": 7,
+			"class" : "knight",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 10 }
+			]
+		},
+		{
+			"id": 8,
+			"class" : "cleric",
+			"female": false,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 27, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 27, "info": 0 }
+			]
+		},
+		{
+			"id": 9,
+			"class" : "cleric",
+			"female": true,
+			"spell": 41,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 4, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":6, "val": 3, "subtype": 41, "info": 0 }
+			]
+		},
+		{
+			"id": 10,
+			"class" : "cleric",
+			"female": false,
+			"spell": 45,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 13, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 45, "info": 0 }
+			]
+		},
+		{
+			"id": 11,
+			"class" : "cleric",
+			"female": true,
+			"spell": 20,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 20, "info": 0 }
+			]
+		},
+		{
+			"id": 12,
+			"class" : "cleric",
+			"female": false,
+			"spell": 42,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 8, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 8 }
+			]
+		},
+		{
+			"id": 13,
+			"class" : "cleric",
+			"female": true,
+			"spell": 35,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 11, "info": 0 }
+			]
+		},
+		{
+			"id": 14,
+			"class" : "cleric",
+			"spell": 48,
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 21, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 48, "info": 0 }
+			]
+		},
+		{
+			"id": 15,
+			"class" : "cleric",
+			"female": true,
+			"spell": 37,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 16,
+			"class" : "ranger",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 23, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 23, "info": 0 }
+			]
+		},
+		{
+			"id": 17,
+			"class" : "ranger",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 9, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 16 }
+			]
+		},
+		{
+			"id": 18,
+			"class" : "ranger",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 1, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 19,
+			"class" : "ranger",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 4, "level": 1 },
+				{ "skill": 6, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 22 }
+			]
+		},
+		{
+			"id": 20,
+			"class" : "ranger",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 26, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 26, "info": 0 }
+			]
+		},
+		{
+			"id": 21,
+			"class" : "ranger",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 1, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 18 }
+			]
+		},
+		{
+			"id": 22,
+			"class" : "ranger",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 0, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 24 }
+			]
+		},
+		{
+			"id": 23,
+			"class" : "ranger",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 1, "level": 1 },
+				{ "skill": 2, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 2, "info": 0 }
+			]
+		},
+		{
+			"id": 24,
+			"class" : "druid",
+			"spell": 55,
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 18, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 55, "info": 1 }
+			]
+		},
+		{
+			"id": 25,
+			"class" : "druid",
+			"female": false,
+			"spell": 37,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 2 },
+				{ "skill": 10, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 37, "info": 0 }
+			]
+		},
+		{
+			"id": 26,
+			"class" : "druid",
+			"female": false,
+			"spell": 42,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 24, "info": 0 }
+			]
+		},
+		{
+			"id": 27,
+			"class" : "druid",
+			"female": true,
+			"spell": 0,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 27, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 27, "info": 0 }
+			]
+		},
+		{
+			"id": 28,
+			"class" : "druid",
+			"female": false,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 11, "info": 0 }
+			]
+		},
+		{
+			"id": 29,
+			"class" : "druid",
+			"spell": 51,
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 9, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":7, "val": 0, "subtype": 51, "info": 0 }
+			]
+		},
+		{
+			"id": 30,
+			"class" : "druid",
+			"female": false,
+			"spell": 16,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 16, "info": 0 }
+			]
+		},
+		{
+			"id": 31,
+			"class" : "druid",
+			"female": false,
+			"spell": 30,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 3, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 20 }
+			]
+		},
+		{
+			"id": 32,
+			"class" : "alchemist",
+			"female": false,
+			"spell": 27,
+			"skill_set":
+			[
+				{ "skill": 3, "level": 1 },
+				{ "skill": 8, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 30 }
+			]
+		},
+		{
+			"id": 33,
+			"class" : "alchemist",
+			"female": false,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 18, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 36 }
+			]
+		},
+		{
+			"id": 34,
+			"class" : "alchemist",
+			"spell": 53,
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 8, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 32 }
+			]
+		},
+		{
+			"id": 35,
+			"class" : "alchemist",
+			"female": true,
+			"spell": 27,
+			"skill_set":
+			[
+				{ "skill": 18, "level": 1 },
+				{ "skill": 23, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 23, "info": 0 }
+			]
+		},
+		{
+			"id": 36,
+			"class" : "alchemist",
+			"female": false,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 8, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 146 }
+			]
+		},
+		{
+			"id": 37,
+			"class" : "alchemist",
+			"female": false,
+			"spell": 53,
+			"skill_set":
+			[
+				{ "skill": 18, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 38 }
+			]
+		},
+		{
+			"id": 38,
+			"class" : "alchemist",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 8, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 1, "subtype": 1, "info": 0 }
+			]
+		},
+		{
+			"id": 39,
+			"class" : "alchemist",
+			"spell": 15,
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 18, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 36 }
+			]
+		},
+		{
+			"id": 40,
+			"class" : "wizard",
+			"female": false,
+			"spell": 60,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 60, "info": 0 }
+			]
+		},
+		{
+			"id": 41,
+			"class" : "wizard",
+			"female": false,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 8, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 8, "info": 1 }
+			]
+		},
+		{
+			"id": 42,
+			"class" : "wizard",
+			"female": true,
+			"spell": 35,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 11, "info": 0 }
+			]
+		},
+		{
+			"id": 43,
+			"class" : "wizard",
+			"female": true,
+			"spell": 51,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":7, "val": 0, "subtype": 51, "info": 0 }
+			]
+		},
+		{
+			"id": 44,
+			"class" : "wizard",
+			"spell": 27,
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 10, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 34 }
+			]
+		},
+		{
+			"id": 45,
+			"class" : "wizard",
+			"female": false,
+			"spell": 19,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 19, "info": 0 }
+			]
+		},
+		{
+			"id": 46,
+			"class" : "wizard",
+			"female": true,
+			"spell": 53,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 4, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 53, "info": 0 }
+			]
+		},
+		{
+			"id": 47,
+			"class" : "wizard",
+			"female": true,
+			"spell": 42,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 18, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 48,
+			"class" : "demoniac",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 3, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 46 }
+			]
+		},
+		{
+			"id": 49,
+			"class" : "demoniac",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 18, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 52 }
+			]
+		},
+		{
+			"id": 50,
+			"class" : "demoniac",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 48 }
+			]
+		},
+		{
+			"id": 51,
+			"class" : "demoniac",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 19, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 42 }
+			]
+		},
+		{
+			"id": 52,
+			"class" : "demoniac",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 18, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 53,
+			"class" : "demoniac",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 1, "level": 1 },
+				{ "skill": 3, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 42 }
+			]
+		},
+		{
+			"id": 54,
+			"class" : "demoniac",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 20, "level": 1 },
+				{ "skill": 2, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 146 }
+			]
+		},
+		{
+			"id": 55,
+			"class" : "demoniac",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 50 }
+			]
+		},
+		{
+			"id": 56,
+			"class" : "heretic",
+			"spell": 3,
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 24, "info": 0 }
+			]
+		},
+		{
+			"id": 57,
+			"class" : "heretic",
+			"female": false,
+			"spell": 22,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 18, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 22, "info": 0 }
+			]
+		},
+		{
+			"id": 58,
+			"class" : "heretic",
+			"female": false,
+			"spell": 30,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 8, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 8, "info": 1 }
+			]
+		},
+		{
+			"id": 59,
+			"class" : "heretic",
+			"female": true,
+			"spell": 45,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 10, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 45, "info": 0 }
+			]
+		},
+		{
+			"id": 60,
+			"class" : "heretic",
+			"female": false,
+			"spell": 53,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 21, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 1, "subtype": 3, "info": 0 }
+			]
+		},
+		{
+			"id": 61,
+			"class" : "heretic",
+			"female": true,
+			"spell": 43,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 43, "info": 0 }
+			]
+		},
+		{
+			"id": 62,
+			"class" : "heretic",
+			"female": false,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 25, "info": 0 }
+			]
+		},
+		{
+			"id": 63,
+			"class" : "heretic",
+			"female": false,
+			"spell": 21,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 6, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 21, "info": 0 }
+			]
+		},
+		{
+			"id": 64,
+			"class" : "deathknight",
+			"female": false,
+			"spell": 53,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 58 }
+			]
+		},
+		{
+			"id": 65,
+			"class" : "deathknight",
+			"female": false,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 20, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 62 }
+			]
+		},
+		{
+			"id": 66,
+			"class" : "deathknight",
+			"female": false,
+			"spell": 54,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 21, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 64 }
+			]
+		},
+		{
+			"id": 67,
+			"class" : "deathknight",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 60 }
+			]
+		},
+		{
+			"id": 68,
+			"class" : "deathknight",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 66 }
+			]
+		},
+		{
+			"id": 69,
+			"class" : "deathknight",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 12, "info": 0 }
+			]
+		},
+		{
+			"id": 70,
+			"class" : "deathknight",
+			"female": false,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 71,
+			"class" : "deathknight",
+			"female": false,
+			"spell": 27,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 23, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 56 }
+			]
+		},
+		{
+			"id": 72,
+			"class" : "necromancer",
+			"female": true,
+			"spell": 24,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 18, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 24, "info": 0 }
+			]
+		},
+		{
+			"id": 73,
+			"class" : "necromancer",
+			"female": true,
+			"spell": 23,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 7, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 23, "info": 0 }
+			]
+		},
+		{
+			"id": 74,
+			"class" : "necromancer",
+			"female": false,
+			"spell": 54,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 25, "info": 0 }
+			]
+		},
+		{
+			"id": 75,
+			"class" : "necromancer",
+			"female": false,
+			"spell": 27,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 11, "info": 1 }
+			]
+		},
+		{
+			"id": 76,
+			"class" : "necromancer",
+			"female": false,
+			"spell": 39,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 8, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 39, "subtype": 0, "info": 3 }
+			]
+		},
+		{
+			"id": 77,
+			"class" : "necromancer",
+			"female": true,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 21, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 46, "info": 0 }
+			]
+		},
+		{
+			"id": 78,
+			"class" : "necromancer",
+			"female": true,
+			"spell": 42,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 12, "info": 0 }
+			]
+		},
+		{
+			"id": 79,
+			"class" : "necromancer",
+			"female": false,
+			"spell": 30,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 80,
+			"class" : "warlock",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 3, "level": 1 },
+				{ "skill": 6, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 72 }
+			]
+		},
+		{
+			"id": 81,
+			"class" : "warlock",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 20, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 146 }
+			]
+		},
+		{
+			"id": 82,
+			"class" : "warlock",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 19, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 78 }
+			]
+		},
+		{
+			"id": 83,
+			"class" : "warlock",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 74 }
+			]
+		},
+		{
+			"id": 84,
+			"class" : "warlock",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 85,
+			"class" : "warlock",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 2, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 2, "info": 0 }
+			]
+		},
+		{
+			"id": 86,
+			"class" : "warlock",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 18, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 80 }
+			]
+		},
+		{
+			"id": 87,
+			"class" : "warlock",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 19, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 70 }
+			]
+		},
+		{
+			"id": 88,
+			"class" : "overlord",
+			"spell": 38,
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 18, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 38, "info": 0 }
+			]
+		},
+		{
+			"id": 89,
+			"class" : "overlord",
+			"female": false,
+			"spell": 27,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 8, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 8, "info": 1 }
+			]
+		},
+		{
+			"id": 90,
+			"class" : "overlord",
+			"female": false,
+			"spell": 43,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 25, "info": 0 }
+			]
+		},
+		{
+			"id": 91,
+			"class" : "overlord",
+			"female": true,
+			"spell": 38,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 38, "info": 0 }
+			]
+		},
+		{
+			"id": 92,
+			"class" : "overlord",
+			"female": false,
+			"spell": 54,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 11, "info": 1 }
+			]
+		},
+		{
+			"id": 93,
+			"class" : "overlord",
+			"female": false,
+			"spell": 23,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 3, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":3, "val": 3, "subtype": 23, "info": 0 }
+			]
+		},
+		{
+			"id": 94,
+			"class" : "overlord",
+			"female": true,
+			"spell": 30,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 1, "subtype": 4, "info": 0 }
+			]
+		},
+		{
+			"id": 95,
+			"class" : "overlord",
+			"female": false,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 21, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 46, "info": 0 }
+			]
+		},
+		{
+			"id": 96,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 1 },
+				{ "skill": 10, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 94 }
+			]
+		},
+		{
+			"id": 97,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 1 },
+				{ "skill": 20, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 146 }
+			]
+		},
+		{
+			"id": 98,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 1 },
+				{ "skill": 1, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 88 }
+			]
+		},
+		{
+			"id": 99,
+			"class" : "barbarian",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 1 },
+				{ "skill": 3, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 92 }
+			]
+		},
+		{
+			"id": 100,
+			"class" : "barbarian",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 1 },
+				{ "skill": 0, "level": 1 }
+			]
+		},
+		{
+			"id": 101,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 84 }
+			]
+		},
+		{
+			"id": 102,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 90 }
+			]
+		},
+		{
+			"id": 103,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 22, "info": 0 }
+			]
+		},
+		{
+			"id": 104,
+			"class" : "battlemage",
+			"spell": 43,
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 86 }
+			]
+		},
+		{
+			"id": 105,
+			"class" : "battlemage",
+			"female": false,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 6, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 25, "info": 0 }
+			]
+		},
+		{
+			"id": 106,
+			"class" : "battlemage",
+			"female": true,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 2, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 90 }
+			]
+		},
+		{
+			"id": 107,
+			"class" : "battlemage",
+			"female": false,
+			"spell": 53,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 2, "info": 0 }
+			]
+		},
+		{
+			"id": 108,
+			"class" : "battlemage",
+			"female": false,
+			"spell": 44,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 20, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 53, "info": 0 }
+			]
+		},
+		{
+			"id": 109,
+			"class" : "battlemage",
+			"spell": 54,
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 44, "info": 0 }
+			]
+		},
+		{
+			"id": 110,
+			"class" : "battlemage",
+			"female": true,
+			"spell": 30,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 25, "info": 0 }
+			]
+		},
+		{
+			"id": 111,
+			"class" : "battlemage",
+			"female": false,
+			"spell": 43,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 11, "info": 1 }
+			]
+		},
+		{
+			"id": 112,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 1 },
+				{ "skill": 26, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 1, "subtype": 5, "info": 0 }
+			]
+		},
+		{
+			"id": 113,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 1 },
+				{ "skill": 6, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 106 }
+			]
+		},
+		{
+			"id": 114,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 1 },
+				{ "skill": 1, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 98 }
+			]
+		},
+		{
+			"id": 115,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 100 }
+			]
+		},
+		{
+			"id": 116,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 23, "info": 0 }
+			]
+		},
+		{
+			"id": 117,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 1 },
+				{ "skill": 0, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 102 }
+			]
+		},
+		{
+			"id": 118,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 1 },
+				{ "skill": 20, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 104 }
+			]
+		},
+		{
+			"id": 119,
+			"class" : "beastmaster",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 23, "level": 1 },
+				{ "skill": 3, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 146 }
+			]
+		},
+		{
+			"id": 120,
+			"class" : "witch",
+			"spell": 45,
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 108 }
+			]
+		},
+		{
+			"id": 121,
+			"class" : "witch",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 8, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 8, "info": 1 }
+			]
+		},
+		{
+			"id": 122,
+			"class" : "witch",
+			"female": true,
+			"spell": 54,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 5, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 2, "subtype": 5, "info": 1 }
+			]
+		},
+		{
+			"id": 123,
+			"class" : "witch",
+			"female": true,
+			"spell": 31,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 27, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 27, "info": 1 }
+			]
+		},
+		{
+			"id": 124,
+			"class" : "witch",
+			"female": true,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 21, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 46, "info": 0 }
+			]
+		},
+		{
+			"id": 125,
+			"class" : "witch",
+			"female": true,
+			"spell": 27,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 25, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 25, "info": 0 }
+			]
+		},
+		{
+			"id": 126,
+			"class" : "witch",
+			"female": true,
+			"spell": 35,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 24, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 24, "info": 0 }
+			]
+		},
+		{
+			"id": 127,
+			"class" : "witch",
+			"female": true,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 11, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":2, "val": 5, "subtype": 11, "info": 1 }
+			]
+		},
+		{
+			"id": 128,
+			"class" : "planeswalker",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 20, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 3, "subtype": 1, "info": 120 },
+				{ "type":4, "val": 3, "subtype": 2, "info": 120 }
+			]
+		},
+		{
+			"id": 129,
+			"class" : "planeswalker",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 13, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 2, "subtype": 1, "info": 113 },
+				{ "type":4, "val": 1, "subtype": 2, "info": 113 },
+				{ "type":4, "val": 5, "subtype": 4, "info": 113 }
+			]
+		},
+		{
+			"id": 130,
+			"class" : "planeswalker",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 20, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 1, "subtype": 1, "info": 114 },
+				{ "type":4, "val": 2, "subtype": 1, "info": 114 },
+				{ "type":4, "val": 2, "subtype": 3, "info": 114 }
+			]
+		},
+		{
+			"id": 131,
+			"class" : "planeswalker",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 19, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 2, "subtype": 1, "info": 115 }
+			]
+		},
+		{
+			"id": 132,
+			"class" : "planeswalker",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 2, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 3, "subtype": 1, "info": 120 },
+				{ "type":4, "val": 3, "subtype": 2, "info": 120 }
+			]
+		},
+		{
+			"id": 133,
+			"class" : "planeswalker",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 13, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 2, "subtype": 1, "info": 113 },
+				{ "type":4, "val": 1, "subtype": 2, "info": 113 },
+				{ "type":4, "val": 5, "subtype": 4, "info": 113 }
+			]
+		},
+		{
+			"id": 134,
+			"class" : "planeswalker",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 1, "subtype": 1, "info": 114 },
+				{ "type":4, "val": 2, "subtype": 1, "info": 114 },
+				{ "type":4, "val": 2, "subtype": 3, "info": 114 }
+			]
+		},
+		{
+			"id": 135,
+			"class" : "planeswalker",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 19, "level": 1 },
+				{ "skill": 21, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 2, "subtype": 1, "info": 115 }
+			]
+		},
+		{
+			"id": 136,
+			"class" : "elementalist",
+			"spell": 13,
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 14, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":5, "val": 100, "subtype": 13, "info": 0 }
+			]
+		},
+		{
+			"id": 137,
+			"class" : "elementalist",
+			"female": true,
+			"spell": 53,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 15, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 53, "info": 0 }
+			]
+		},
+		{
+			"id": 138,
+			"class" : "elementalist",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 16, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":5, "val": 50, "subtype": 15, "info": 0 }
+			]
+		},
+		{
+			"id": 139,
+			"class" : "elementalist",
+			"female": true,
+			"spell": 46,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 17, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 46, "info": 0 }
+			]
+		},
+		{
+			"id": 140,
+			"class" : "elementalist",
+			"female": false,
+			"spell": 43,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 14, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 43, "info": 0 }
+			]
+		},
+		{
+			"id": 141,
+			"class" : "elementalist",
+			"female": false,
+			"spell": 47,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 15, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":8, "val": 0, "subtype": 47, "info": 0 }
+			]
+		},
+		{
+			"id": 142,
+			"class" : "elementalist",
+			"female": false,
+			"spell": 35,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 16, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 143,
+			"class" : "elementalist",
+			"female": false,
+			"spell": 54,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 17, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":10, "val": 350, "subtype": 6, "info": 0 }
+			]
+		},
+		{
+			"id": 144,
+			"class" : "knight",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":12, "val": 2, "subtype": 0, "info": 0 }
+			]
+		},
+		{
+			"id": 145,
+			"class" : "witch",
+			"female": true,
+			"spell": 22,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 1 },
+				{ "skill": 14, "level": 3 } ],
+			"specialties":
+			[
+				{ "type":11, "val": 14, "subtype": 0, "info": 0 }
+			]
+		},
+		{
+			"id": 146,
+			"class" : "knight",
+			"female": true,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 4 }
+			]
+		},
+		{
+			"id": 147,
+			"class" : "wizard",
+			"female": false,
+			"spell": 53,
+			"skill_set":
+			[
+				{ "skill": 7, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":9, "val": 0, "subtype": 8, "info": 136 },
+				{ "type":9, "val": 0, "subtype": 34, "info": 136 }
+			]
+		},
+		{
+			"id": 148,
+			"class" : "ranger",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 1, "level": 1 },
+				{ "skill": 6, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":9, "val": 0, "subtype": 2, "info": 137 },
+				{ "type":9, "val": 0, "subtype": 18, "info": 137 }
+			]
+		},
+		{
+			"id": 149,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 22, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 5,  "subtype": 1, "info": 96 },
+				{ "type":4, "val": 5,  "subtype": 2, "info": 96 },
+				{ "type":4, "val": 10, "subtype": 3, "info": 96 }
+			]
+		},
+		{
+			"id": 150,
+			"class" : "deathknight",
+			"female": false,
+			"spell": 54,
+			"skill_set":
+			[
+				{ "skill": 12, "level": 2 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 5,  "subtype": 1, "info": 66 },
+				{ "type":4, "val": 5,  "subtype": 2, "info": 66 },
+				{ "type":4, "val": 10, "subtype": 3, "info": 66 }
+			]
+		},
+		{
+			"id": 151,
+			"class" : "warlock",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 13, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":13, "val": 5, "subtype": 1, "info": 0 },
+				{ "type":13, "val": 5, "subtype": 2, "info": 0 }
+			]
+		},
+		{
+			"id": 152,
+			"class" : "knight",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 23, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 4 }
+			]
+		},
+		{
+			"id": 153,
+			"class" : "warlock",
+			"female": true,
+			"spell": 15,
+			"skill_set":
+			[
+				{ "skill": 13, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":13, "val": 1, "subtype": 1, "info": 5 },
+				{ "type":13, "val": 1, "subtype": 1, "info": 5 }
+			]
+		},
+		{
+			"id": 154,
+			"class" : "barbarian",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 19, "level": 1 },
+				{ "skill": 22, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":1, "val": 0, "subtype": 0, "info": 90 }
+			]
+		},
+		{
+			"id": 155,
+			"class" : "demoniac",
+			"female": false,
+			"skill_set":
+			[
+				{ "skill": 6, "level": 1 },
+				{ "skill": 19, "level": 1 }
+			],
+			"specialties":
+			[
+				{ "type":4, "val": 4, "subtype": 1, "info": 54 },
+				{ "type":4, "val": 2, "subtype": 2, "info": 54 },
+				{ "type":4, "val": 1, "subtype": 5, "info": 54 }
+			]
+		}
 	]
 }

+ 1 - 0
lib/CArtHandler.cpp

@@ -310,6 +310,7 @@ void CArtHandler::loadArtifacts(bool onlyTxt)
 		}
 		CArtifact &nart = *art;
 		nart.id=i;
+		nart.iconIndex=i;
 		nart.setName (parser.readString());
 		nart.setEventText (events.readString());
 		events.endLine();

+ 2 - 2
lib/CGameState.cpp

@@ -403,7 +403,7 @@ CGHeroInstance * CGameState::HeroesPool::pickHeroFor(bool native, TPlayerColor p
 		for(auto i=available.begin(); i!=available.end(); i++)
 		{
 			if(pavailable.find(i->first)->second & 1<<player
-				&& i->second->type->heroType/2 == town->typeID)
+				&& i->second->type->heroClass->faction == town->typeID)
 			{
 				pool.push_back(i->second); //get all available heroes
 			}
@@ -680,7 +680,7 @@ void CGameState::randomizeObject(CGObjectInstance *cur)
 		cur->ID = ran.first;
 		h->portrait = cur->subID = ran.second;
 		h->type = VLC->heroh->heroes[ran.second];
-		h->randomizeArmy(h->type->heroType/2);
+		h->randomizeArmy(h->type->heroClass->faction);
 		map->heroes.push_back(h);
 		return; //TODO: maybe we should do something with definfo?
 	}

+ 10 - 0
lib/CGeneralTextHandler.h

@@ -35,6 +35,16 @@ public:
 	std::string readString();
 	float readNumber();
 
+	template <typename numeric>
+	std::vector<numeric> readNumArray(size_t size)
+	{
+		std::vector<numeric> ret;
+		ret.reserve(size);
+		while (size--)
+			ret.push_back(readNumber());
+		return ret;
+	}
+
 	/// returns true if next entry is empty
 	bool isNextEntryEmpty();
 

+ 82 - 73
lib/CHeroHandler.cpp

@@ -5,7 +5,7 @@
 #include "Filesystem/CResourceLoader.h"
 #include "VCMI_Lib.h"
 #include "JsonNode.h"
-#include "GameConstants.h"
+#include "StringConstants.h"
 #include "BattleHex.h"
 #include "CModHandler.h"
 
@@ -21,7 +21,6 @@
 
 CHeroClass::CHeroClass()
 {
-	skillLimit = 8;
 }
 CHeroClass::~CHeroClass()
 {
@@ -33,12 +32,12 @@ int CHeroClass::chooseSecSkill(const std::set<int> & possibles) const //picks se
 	int totalProb = 0;
 	for(std::set<int>::const_iterator i=possibles.begin(); i!=possibles.end(); i++)
 	{
-		totalProb += proSec[*i];
+		totalProb += secSkillProbability[*i];
 	}
 	int ran = rand()%totalProb;
 	for(std::set<int>::const_iterator i=possibles.begin(); i!=possibles.end(); i++)
 	{
-		ran -= proSec[*i];
+		ran -= secSkillProbability[*i];
 		if(ran<0)
 			return *i;
 	}
@@ -47,7 +46,7 @@ int CHeroClass::chooseSecSkill(const std::set<int> & possibles) const //picks se
 
 EAlignment::EAlignment CHeroClass::getAlignment() const
 {
-	return (EAlignment::EAlignment)alignment;
+	return EAlignment::EAlignment(VLC->townh->factions[faction].alignment);
 }
 
 std::vector<BattleHex> CObstacleInfo::getBlocked(BattleHex hex) const
@@ -83,18 +82,78 @@ bool CObstacleInfo::isAppropriate(int terrainType, int specialBattlefield /*= -1
 	return vstd::contains(allowedTerrains, terrainType);
 }
 
-CHeroHandler::~CHeroHandler()
+void CHeroClassHandler::load()
 {
-	for (int i = 0; i < heroes.size(); i++)
-		heroes[i].dellNull();
+	CLegacyConfigParser parser("DATA/HCTRAITS.TXT");
+
+	parser.endLine(); // header
+	parser.endLine();
+
+	do
+	{
+		CHeroClass * hc = new CHeroClass;
+
+		hc->name             = parser.readString();
+		hc->aggression       = parser.readNumber();
+		hc->id = heroClasses.size();
+
+		hc->primarySkillInitial   = parser.readNumArray<int>(GameConstants::PRIMARY_SKILLS);
+		hc->primarySkillLowLevel  = parser.readNumArray<int>(GameConstants::PRIMARY_SKILLS);
+		hc->primarySkillHighLevel = parser.readNumArray<int>(GameConstants::PRIMARY_SKILLS);
+
+		hc->secSkillProbability   = parser.readNumArray<int>(GameConstants::SKILL_QUANTITY);
 
-	for (int i = 0; i < heroClasses.size(); i++)
-		delete heroClasses[i];
+		for(int dd=0; dd<GameConstants::F_NUMBER; ++dd)
+		{
+			hc->selectionProbability[dd] = parser.readNumber();
+		}
+
+		VLC->modh->identifiers.requestIdentifier("faction." + ETownType::names[heroClasses.size()/2],
+		[=](si32 faction)
+		{
+			hc->faction = faction;
+		});
+
+		heroClasses.push_back(hc);
+		VLC->modh->identifiers.registerObject("heroClass." + GameConstants::HERO_CLASSES_NAMES[hc->id], hc->id);
+	}
+	while (parser.endLine() && !parser.isNextEntryEmpty());
+}
+
+void CHeroClassHandler::load(const JsonNode & classes)
+{
+	//TODO
+}
+
+void CHeroClassHandler::loadClass(const JsonNode & heroClass)
+{
+	//TODO
+}
+
+CHeroClassHandler::~CHeroClassHandler()
+{
+	BOOST_FOREACH(auto heroClass, heroClasses)
+	{
+		delete heroClass.get();
+	}
+}
+
+CHeroHandler::~CHeroHandler()
+{
+	BOOST_FOREACH(auto hero, heroes)
+		delete hero.get();
 }
 
 CHeroHandler::CHeroHandler()
 {}
 
+void CHeroHandler::load()
+{
+	classes.load();
+	loadHeroes();
+	loadObstacles();
+}
+
 void CHeroHandler::loadObstacles()
 {
 	auto loadObstacles = [](const JsonNode &node, bool absolute, std::map<int, CObstacleInfo> &out)
@@ -154,20 +213,20 @@ void CHeroHandler::loadHeroes()
 	// Load heroes information
 	const JsonNode config(ResourceID("config/heroes.json"));
 	BOOST_FOREACH(const JsonNode &hero, config["heroes"].Vector()) {
-		int hid = hero["id"].Float();
+
+		CHero * currentHero = heroes[hero["id"].Float()];
 		const JsonNode *value;
 
 		// sex: 0=male, 1=female
-		heroes[hid]->sex = !!hero["female"].Bool();
-		heroes[hid]->heroType = CHero::EHeroClasses((int)hero["class"].Float());
+		currentHero->sex = !!hero["female"].Bool();
 
 		BOOST_FOREACH(const JsonNode &set, hero["skill_set"].Vector()) {
-			heroes[hid]->secSkillsInit.push_back(std::make_pair(set["skill"].Float(), set["level"].Float()));
+			currentHero->secSkillsInit.push_back(std::make_pair(set["skill"].Float(), set["level"].Float()));
 		}
 
 		value = &hero["spell"];
 		if (!value->isNull()) {
-			heroes[hid]->startingSpell = value->Float();
+			currentHero->startingSpell = value->Float();
 		}
 
 		BOOST_FOREACH(const JsonNode &specialty, hero["specialties"].Vector())
@@ -179,12 +238,17 @@ void CHeroHandler::loadHeroes()
 			dummy.subtype = specialty["subtype"].Float();
 			dummy.additionalinfo = specialty["info"].Float();
 
-			heroes[hid]->spec.push_back(dummy); //put a copy of dummy
+			currentHero->spec.push_back(dummy); //put a copy of dummy
 		}
+
+		VLC->modh->identifiers.requestIdentifier("heroClass." + hero["class"].String(),
+		[=](si32 classID)
+		{
+			currentHero->heroClass = classes.heroClasses[classID];
+		});
 	}
 
-	loadHeroClasses();
-	initHeroClasses();
+	loadTerrains();
 	expPerLevel.push_back(0);
 	expPerLevel.push_back(1000);
 	expPerLevel.push_back(2000);
@@ -232,61 +296,6 @@ void CHeroHandler::loadHeroes()
 	while (ballParser.endLine());
 }
 
-void CHeroHandler::loadHeroClasses()
-{
-	CLegacyConfigParser parser("DATA/HCTRAITS.TXT");
-
-	parser.endLine(); // header
-	parser.endLine();
-
-	do
-	{
-		CHeroClass * hc = new CHeroClass;
-		hc->alignment = heroClasses.size() / 6;
-
-		hc->name             = parser.readString();
-		hc->aggression       = parser.readNumber();
-		for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
-		{
-			hc->initialPrimSkills[g] = parser.readNumber();
-		}
-
-		hc->primChance.resize(GameConstants::PRIMARY_SKILLS);
-		for(int x=0; x<GameConstants::PRIMARY_SKILLS; ++x)
-		{
-			hc->primChance[x].first = parser.readNumber();
-		}
-		for(int x=0; x<GameConstants::PRIMARY_SKILLS; ++x)
-		{
-			hc->primChance[x].second = parser.readNumber();
-		}
-
-		hc->proSec.resize(GameConstants::SKILL_QUANTITY);
-		for(int dd=0; dd<GameConstants::SKILL_QUANTITY; ++dd)
-		{
-			hc->proSec[dd] = parser.readNumber();
-		}
-
-		for(int dd=0; dd<GameConstants::F_NUMBER; ++dd)
-		{
-			hc->selectionProbability[dd] = parser.readNumber();
-		}
-
-		heroClasses.push_back(hc);
-	}
-	while (parser.endLine() && !parser.isNextEntryEmpty());
-}
-
-void CHeroHandler::initHeroClasses()
-{
-	for(int gg=0; gg<heroes.size(); ++gg)
-	{
-		heroes[gg]->heroClass = heroClasses[heroes[gg]->heroType];
-	}
-
-	loadTerrains();
-}
-
 ui32 CHeroHandler::level (ui64 experience) const
 {
 	int i;

+ 46 - 28
lib/CHeroHandler.h

@@ -18,6 +18,7 @@ class CDefHandler;
 class CGameInfo;
 class CGHeroInstance;
 struct BattleHex;
+class JsonNode;
 
 struct SSpecialtyInfo
 {	si32 type;
@@ -45,17 +46,12 @@ public:
 		}
 	};
 
-	enum EHeroClasses {KNIGHT, CLERIC, RANGER, DRUID, ALCHEMIST, WIZARD,
-		DEMONIAC, HERETIC, DEATHKNIGHT, NECROMANCER, WARLOCK, OVERLORD,
-		BARBARIAN, BATTLEMAGE, BEASTMASTER, WITCH, PLANESWALKER, ELEMENTALIST};
-
 	std::string name; //name of hero
 	si32 ID;
 
 	InitialArmyStack initialArmy[3];
 
 	CHeroClass * heroClass;
-	EHeroClasses heroType; //hero class
 	std::vector<std::pair<ui8,ui8> > secSkillsInit; //initial secondary skills; first - ID of skill, second - level of skill (1 - basic, 2 - adv., 3 - expert)
 	std::vector<SSpecialtyInfo> spec;
 	si32 startingSpell; //-1 if none
@@ -67,20 +63,25 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & name & ID & initialArmy & heroClass & heroType & secSkillsInit & spec & startingSpell & sex;
+		h & name & ID & initialArmy & heroClass & secSkillsInit & spec & startingSpell & sex;
 	}
 };
 
 class DLL_LINKAGE CHeroClass
 {
 public:
-	ui8 alignment; 
-	ui32 skillLimit; //how many secondary skills can hero learn
-	std::string name;
+	std::string identifier;
+	std::string name; // translatable
 	double aggression;
-	int initialPrimSkills[GameConstants::PRIMARY_SKILLS]; //initial values of primary skills, uses PrimarySkill enum
-	std::vector<std::pair<int,int> > primChance;//primChance[PRIMARY_SKILL_ID] - first is for levels 2 - 9, second for 10+;;; probability (%) of getting point of primary skill when getting new level
-	std::vector<int> proSec; //probabilities of gaining secondary skills (out of 112), in id order
+	TFaction faction;
+	ui8 id;
+
+	std::vector<int> primarySkillInitial;  // initial primary skills
+	std::vector<int> primarySkillLowLevel; // probability (%) of getting point of primary skill when getting level
+	std::vector<int> primarySkillHighLevel;// same for high levels (> 10)
+
+	std::vector<int> secSkillProbability; //probabilities of gaining secondary skills (out of 112), in id order
+
 	std::map<TFaction, int> selectionProbability; //probability of selection in towns
 
 	int chooseSecSkill(const std::set<int> & possibles) const; //picks secondary skill out from given possibilities
@@ -89,8 +90,10 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & skillLimit & name & aggression & initialPrimSkills & primChance
-			& proSec & selectionProbability & alignment;
+		h & identifier & name & faction & aggression;
+		h & primarySkillInitial   & primarySkillLowLevel;
+		h & primarySkillHighLevel & secSkillProbability;
+		h & selectionProbability;
 	}
 	EAlignment::EAlignment getAlignment() const;
 };
@@ -116,14 +119,38 @@ struct DLL_LINKAGE CObstacleInfo
 	}
 };
 
+class DLL_LINKAGE CHeroClassHandler
+{
+public:
+	std::vector< ConstTransitivePtr<CHeroClass> > heroClasses;
+
+	/// load from H3 config
+	void load();
+
+	/// load any number of classes from json
+	void load(const JsonNode & classes);
+
+	/// load one class from json
+	void loadClass(const JsonNode & heroClass);
+
+	~CHeroClassHandler();
+
+	template <typename Handler> void serialize(Handler &h, const int version)
+	{
+		h & heroClasses;
+	}
+};
+
 class DLL_LINKAGE CHeroHandler
 {
+	std::vector<ui64> expPerLevel; //expPerLEvel[i] is amount of exp needed to reach level i; if it is not in this vector, multiplicate last value by 1,2 to get next value
+
 public:
+	CHeroClassHandler classes;
+
 	std::vector< ConstTransitivePtr<CHero> > heroes; //changed from nodrze
-	std::vector<CHeroClass *> heroClasses;
-	std::vector<ui64> expPerLevel; //expPerLEvel[i] is amount of exp needed to reach level i; if it is not in this vector, multiplicate last value by 1,2 to get next value
 
-	 //default costs of going through terrains: dirt, sand, grass, snow, swamp, rough, subterranean, lava, water, rock; -1 means terrain is imapassable
+	//default costs of going through terrains: dirt, sand, grass, snow, swamp, rough, subterranean, lava, water, rock; -1 means terrain is imapassable
 	std::vector<int> terrCosts;
 	
 	struct SBallisticsLevelInfo
@@ -147,9 +174,8 @@ public:
 	ui32 level(ui64 experience) const; //calculates level corresponding to given experience amount
 	ui64 reqExp(ui32 level) const; //calculates experience required for given level
 
+	void load();
 	void loadHeroes();
-	void loadHeroClasses();
-	void initHeroClasses();
 	void loadTerrains();
 	CHeroHandler(); //c-tor
 	~CHeroHandler(); //d-tor
@@ -167,15 +193,7 @@ public:
 
 	template <typename Handler> void serialize(Handler &h, const int version)
 	{
-		h & heroClasses & heroes & expPerLevel & ballistics & terrCosts;
+		h & classes & heroes & expPerLevel & ballistics & terrCosts;
 		h & obstacles & absoluteObstacles;
-		if(!h.saving)
-		{
-			//restore class pointers
-			for (int i=0; i<heroes.size(); i++)
-			{
-				heroes[i]->heroClass = heroClasses[heroes[i]->heroType];
-			}
-		}
 	}
 };

+ 1 - 0
lib/CMakeLists.txt

@@ -58,6 +58,7 @@ set(lib_HEADERS
 		CScriptingModule.h
 		CStopWatch.h
 		GameConstants.h
+		StringConstants.h
 		IGameEventsReceiver.h
 		int3.h
 		Interprocess.h

+ 2 - 2
lib/CObjectHandler.cpp

@@ -725,7 +725,7 @@ void CGHeroInstance::initHero()
 	{
 		for(int g=0; g<GameConstants::PRIMARY_SKILLS; ++g)
 		{
-			pushPrimSkill(static_cast<PrimarySkill::PrimarySkill>(g), type->heroClass->initialPrimSkills[g]);
+			pushPrimSkill(static_cast<PrimarySkill::PrimarySkill>(g), type->heroClass->primarySkillInitial[g]);
 		}
 	}
 	if(secSkills.size() == 1 && secSkills[0] == std::pair<ui8,ui8>(-1, -1)) //set secondary skills to default
@@ -753,7 +753,7 @@ void CGHeroInstance::initHero()
 
 	if (VLC->modh->modules.COMMANDERS)
 	{
-		commander = new CCommanderInstance (VLC->creh->factionCommanders[type->heroType / 2]); //hopefully it returns town type
+		commander = new CCommanderInstance (VLC->creh->factionCommanders[type->heroClass->faction]);
 		commander->setArmyObj (castToArmyObj()); //TODO: separate function for setting commanders
 	}
 

+ 2 - 10
lib/CTownHandler.cpp

@@ -4,7 +4,7 @@
 #include "VCMI_Lib.h"
 #include "CGeneralTextHandler.h"
 #include "JsonNode.h"
-#include "GameConstants.h"
+#include "StringConstants.h"
 #include "CModHandler.h"
 #include "Filesystem/CResourceLoader.h"
 
@@ -508,20 +508,12 @@ void CTownHandler::load()
 	JsonNode legacyConfig;
 	loadLegacyData(legacyConfig);
 
-	//hardcoded list of H3 factions. Should be only used to convert H3 configs
-	static const std::string factionName [GameConstants::F_NUMBER] =
-	{
-		"castle", "rampart", "tower",
-		"inferno", "necropolis", "dungeon",
-		"stronghold", "fortress", "conflux"
-	};
-
 	// semi-manually merge legacy config with towns json
 
 	for (size_t i=0; i< legacyConfig.Vector().size(); i++)
 	{
 		JsonNode & legacyFaction = legacyConfig.Vector()[i];
-		JsonNode & outputFaction = buildingsConf[factionName[i]];
+		JsonNode & outputFaction = buildingsConf[ETownType::names[i]];
 
 		if (outputFaction["name"].isNull())
 			outputFaction["name"] = legacyFaction["name"];

+ 0 - 2
lib/CTownHandler.h

@@ -148,8 +148,6 @@ public:
 		h & names & typeID & creatures & buildings & hordeLvl & mageLevel
 			& primaryRes & warMachine & clientInfo;
 	}
-
-	friend class CTownHandler;
 };
 
 struct DLL_LINKAGE SPuzzleInfo

+ 2 - 10
lib/GameConstants.h

@@ -84,17 +84,11 @@ namespace GameConstants
 	const int BATTLE_PENALTY_DISTANCE = 10; //if the distance is > than this, then shooting stack has distance penalty
 
 	const ui16 BACKPACK_START = 19;
-	const int ID_CATAPULT = 3, ID_LOCK = 145;
+	const int ID_CATAPULT = 3, ID_SELECTION=144, ID_LOCK = 145;
 
 	const int TERRAIN_TYPES=10;
-	const std::string TERRAIN_NAMES [TERRAIN_TYPES] = {
-	    "dirt", "sand", "grass", "snow", "swamp", "rough", "subterra", "lava", "water", "rock"
-	};
-
 	const int RESOURCE_QUANTITY=8;
-	const std::string RESOURCE_NAMES [RESOURCE_QUANTITY] = {
-	    "wood", "mercury", "ore", "sulfur", "crystal", "gems", "gold", "mithril"
-	};
+
 }
 
 // Enum declarations
@@ -117,8 +111,6 @@ namespace ELossConditionType
 namespace EAlignment
 {
 	enum EAlignment { GOOD, EVIL, NEUTRAL };
-
-	const std::string names [3] = {"good", "evil", "neutral"}; //for parsing from config file
 }
 
 namespace ETownType

+ 3 - 0
lib/HeroBonus.h

@@ -38,6 +38,9 @@ public:
 
 	virtual int limit(const BonusLimitationContext &context) const; //0 - accept bonus; 1 - drop bonus; 2 - delay (drops eventually)
 	virtual int callNext(const BonusLimitationContext &context) const;
+
+	virtual ~LimiterDecorator()
+	{}
 };
 
 #define BONUS_TREE_DESERIALIZATION_FIX if(!h.saving && h.smartPointerSerialization) deserializationFix();

+ 1 - 1
lib/Map/CCampaignHandler.cpp

@@ -341,7 +341,7 @@ void CCampaignScenario::prepareCrossoverHeroes( std::vector<CGHeroInstance *> he
 			{
 				cgh->getBonusLocalFirst(Selector::type(Bonus::PRIMARY_SKILL) &&
 					Selector::subtype(g) && Selector::sourceType(Bonus::HERO_BASE_SKILL) )->val
-						= cgh->type->heroClass->initialPrimSkills[g];
+						= cgh->type->heroClass->primarySkillInitial[g];
 			}
 		}
 	}

+ 1 - 1
lib/ResourceSet.cpp

@@ -1,6 +1,6 @@
 #include "StdInc.h"
 #include "ResourceSet.h"
-#include "GameConstants.h"
+#include "StringConstants.h"
 #include "JsonNode.h"
 
 Res::ResourceSet::ResourceSet()

+ 67 - 0
lib/StringConstants.h

@@ -0,0 +1,67 @@
+#pragma once
+
+#include "GameConstants.h"
+
+/*
+ * GameConstants.h, part of VCMI engine
+ *
+ * Authors: listed in file AUTHORS in main folder
+ *
+ * License: GNU General Public License v2.0 or later
+ * Full text of license available in license.txt file, in main folder
+ *
+ */
+
+
+///
+/// String ID which are pointless to move to config file - these types are mostly hardcoded
+///
+namespace GameConstants
+{
+	const std::string TERRAIN_NAMES [TERRAIN_TYPES] = {
+	    "dirt", "sand", "grass", "snow", "swamp", "rough", "subterra", "lava", "water", "rock"
+	};
+	
+	const std::string RESOURCE_NAMES [RESOURCE_QUANTITY] = {
+	    "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"
+	};
+}
+
+namespace EAlignment
+{
+	const std::string names [3] = {"good", "evil", "neutral"};
+}
+
+namespace PrimarySkill
+{
+	const std::string names [GameConstants::PRIMARY_SKILLS] = { "attack", "defence", "spellpower", "knowledge" };
+}
+
+namespace SecondarySkill
+{
+	const std::string names [GameConstants::SKILL_QUANTITY] =
+	{
+		"pathfinding",  "archery",      "logistics",    "scouting",     "diplomacy",    //  5
+		"navigation",   "leadership",   "wisdom",       "mysticism",    "luck",         // 10
+		"ballistics",   "eagleEye",     "necromancy",   "estates",      "fireMagic",    // 15
+		"airMagic",     "waterMagic",   "earthMagic",   "scholar",      "tactics",      // 20
+		"artillery",    "learning",     "offence",      "armorer",      "intelligence", // 25
+		"sorcery",      "resistance",   "firstAid"
+	};
+}
+
+namespace ETownType
+{
+	const std::string names [GameConstants::F_NUMBER] =
+	{
+		"castle",       "rampart",      "tower",
+		"inferno",      "necropolis",   "dungeon",
+		"stronghold",   "fortress",     "conflux"
+	};
+}

+ 1 - 2
lib/VCMI_Lib.cpp

@@ -82,8 +82,7 @@ void LibClasses::init()
 	tlog0<<"\tGeneral text handler: "<<pomtime.getDiff()<<std::endl;
 
 	heroh = new CHeroHandler;
-	heroh->loadHeroes();
-	heroh->loadObstacles();
+	heroh->load();
 	tlog0 <<"\tHero handler: "<<pomtime.getDiff()<<std::endl;
 
 	arth = new CArtHandler;

+ 8 - 6
server/CGameHandler.cpp

@@ -215,10 +215,12 @@ void CGameHandler::levelUpHero(int ID)
 	//give prim skill
 	tlog5 << hero->name <<" got level "<<hero->level<<std::endl;
 	int r = rand()%100, pom=0, x=0;
-	int std::pair<int,int>::*g  =  (hero->level>9) ? (&std::pair<int,int>::second) : (&std::pair<int,int>::first);
+
+	auto & skillChances = (hero->level>9) ? hero->type->heroClass->primarySkillLowLevel : hero->type->heroClass->primarySkillHighLevel;
+
 	for(;x<GameConstants::PRIMARY_SKILLS;x++)
 	{
-		pom += hero->type->heroClass->primChance[x].*g;
+		pom += skillChances[x];
 		if(r<pom)
 			break;
 	}
@@ -257,14 +259,14 @@ void CGameHandler::levelUpHero(int ID)
 		hlu.skills.push_back(s);
 		basicAndAdv.erase(s);
 	}
-	else if(none.size() && hero->secSkills.size() < hero->type->heroClass->skillLimit)
+	else if(none.size() && hero->secSkills.size() < GameConstants::SKILL_PER_HERO)
 	{
 		hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(none)); //give new skill
 		none.erase(hlu.skills.back());
 	}
 
 	//second offered skill
-	if(none.size() && hero->secSkills.size() < hero->type->heroClass->skillLimit) //hero have free skill slot
+	if(none.size() && hero->secSkills.size() < GameConstants::SKILL_PER_HERO) //hero have free skill slot
 	{
 		hlu.skills.push_back(hero->type->heroClass->chooseSecSkill(none)); //new skill
 	}
@@ -1695,7 +1697,7 @@ bool CGameHandler::moveHero( si32 hid, int3 dst, ui8 instant, ui8 asker /*= 255*
 		{
 			obj->onHeroLeave(h);
 		}
-		getTilesInRange(tmh.fowRevealed, h->getSightCenter()+(tmh.end-tmh.start), h->getSightRadious(), h->tempOwner, 1);
+		this->getTilesInRange(tmh.fowRevealed, h->getSightCenter()+(tmh.end-tmh.start), h->getSightRadious(), h->tempOwner, 1);
 	};
 
 	auto applyWithResult = [&](TryMoveHero::EResult result) -> bool
@@ -3006,7 +3008,7 @@ bool CGameHandler::buySecSkill( const IMarket *m, const CGHeroInstance *h, int s
 	if (h->secSkills.size() >= GameConstants::SKILL_PER_HERO)//can't learn more skills
 		COMPLAIN_RET("Hero can't learn any more skills");
 
-	if (h->type->heroClass->proSec[skill]==0)//can't learn this skill (like necromancy for most of non-necros)
+	if (h->type->heroClass->secSkillProbability[skill]==0)//can't learn this skill (like necromancy for most of non-necros)
 		COMPLAIN_RET("The hero can't learn this skill!");
 
 	if(!vstd::contains(m->availableItemsIds(EMarketMode::RESOURCE_SKILL), skill))