소스 검색

skill names and descriptions are fully managed by CSkillHandler

Henning Koehler 8 년 전
부모
커밋
abdca71828

+ 0 - 8
client/CGameInfo.cpp

@@ -37,11 +37,3 @@ void CGameInfo::setFromLib()
 	skillh = VLC->skillh;
 	objtypeh = VLC->objtypeh;
 }
-
-const std::string & CGameInfo::skillInfo(int skill, int level) const
-{
-	const std::string & desc = (*skillh)[SecondarySkill(skill)]->getDescription(level);
-	if(desc.size() > 0)
-		return desc;
-	return generaltexth->skillInfoTexts[skill][level-1];
-}

+ 0 - 1
client/CGameInfo.h

@@ -68,6 +68,5 @@ public:
 	friend class CClient;
 
 	CGameInfo();
-	const std::string & skillInfo(int skill, int level) const;
 };
 extern const CGameInfo* CGI;

+ 2 - 1
client/CPreGame.cpp

@@ -18,6 +18,7 @@
 #include "CGameInfo.h"
 #include "gui/CCursorHandler.h"
 #include "../lib/CGeneralTextHandler.h"
+#include "../lib/CSkillHandler.h"
 #include "../lib/CTownHandler.h"
 #include "../lib/CHeroHandler.h"
 #include "../lib/mapping/CCampaignHandler.h"
@@ -3624,7 +3625,7 @@ void CBonusSelection::updateBonusSelection()
 			desc = CGI->generaltexth->allTexts[718];
 
 			boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->levels[bonDescs[i].info3 - 1]); //skill level
-			boost::algorithm::replace_first(desc, "%s", CGI->generaltexth->skillName[bonDescs[i].info2]); //skill name
+			boost::algorithm::replace_first(desc, "%s", CGI->skillh->skillName(bonDescs[i].info2)); //skill name
 			picNumber = bonDescs[i].info2 * 3 + bonDescs[i].info3 - 1;
 
 			break;

+ 3 - 2
client/widgets/CComponent.cpp

@@ -22,6 +22,7 @@
 #include "../../lib/CArtHandler.h"
 #include "../../lib/CTownHandler.h"
 #include "../../lib/CCreatureHandler.h"
+#include "../../lib/CSkillHandler.h"
 #include "../../lib/spells/CSpellHandler.h"
 #include "../../lib/CGeneralTextHandler.h"
 #include "../../lib/NetPacksBase.h"
@@ -148,7 +149,7 @@ std::string CComponent::getDescription()
 	{
 	case primskill:  return (subtype < 4)? CGI->generaltexth->arraytxt[2+subtype] //Primary skill
 										 : CGI->generaltexth->allTexts[149]; //mana
-	case secskill:   return CGI->skillInfo(subtype,val);
+	case secskill:   return CGI->skillh->skillInfo(subtype, val);
 	case resource:   return CGI->generaltexth->allTexts[242];
 	case creature:   return "";
 	case artifact:
@@ -192,7 +193,7 @@ std::string CComponent::getSubtitleInternal()
 	switch(compType)
 	{
 	case primskill:  return boost::str(boost::format("%+d %s") % val % (subtype < 4 ? CGI->generaltexth->primarySkillNames[subtype] : CGI->generaltexth->allTexts[387]));
-	case secskill:   return CGI->generaltexth->levels[val-1] + "\n" + CGI->generaltexth->skillName[subtype];
+	case secskill:   return CGI->generaltexth->levels[val-1] + "\n" + CGI->skillh->skillName(subtype);
 	case resource:   return boost::lexical_cast<std::string>(val);
 	case creature:   return (val? boost::lexical_cast<std::string>(val) + " " : "") + CGI->creh->creatures[subtype]->*(val != 1 ? &CCreature::namePl : &CCreature::nameSing);
 	case artifact:   return CGI->arth->artifacts[subtype]->Name();

+ 4 - 3
client/windows/CHeroWindow.cpp

@@ -33,6 +33,7 @@
 #include "../lib/CConfigHandler.h"
 #include "../lib/CGeneralTextHandler.h"
 #include "../lib/CHeroHandler.h"
+#include "../lib/CSkillHandler.h"
 #include "../lib/mapObjects/CGHeroInstance.h"
 #include "../lib/NetPacksBase.h"
 #include "../mapHandler.h"
@@ -240,8 +241,8 @@ void CHeroWindow::update(const CGHeroInstance * hero, bool redrawNeeded)
 			level = curHero->getSecSkillLevel(SecondarySkill(curHero->secSkills[g].first));
 		secSkillAreas[g]->type = skill;
 		secSkillAreas[g]->bonusValue = level;
-		secSkillAreas[g]->text = CGI->skillInfo(skill,level);
-		secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->generaltexth->skillName[skill]);
+		secSkillAreas[g]->text = CGI->skillh->skillInfo(skill, level);
+		secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % CGI->generaltexth->levels[level-1] % CGI->skillh->skillName(skill));
 		secSkillImages[g]->setFrame(skill*3 + level + 2);
 	}
 
@@ -372,7 +373,7 @@ void CHeroWindow::showAll(SDL_Surface * to)
 	for(size_t v=0; v<std::min(secSkillAreas.size(), curHero->secSkills.size()); ++v)
 	{
 	 	printAtLoc(CGI->generaltexth->levels[curHero->secSkills[v].second-1], (v%2) ? 212 : 68, 280 + 48 * (v/2), FONT_SMALL, Colors::WHITE, to);
-	 	printAtLoc(CGI->generaltexth->skillName[curHero->secSkills[v].first], (v%2) ? 212 : 68, 300 + 48 * (v/2), FONT_SMALL, Colors::WHITE, to);
+		printAtLoc(CGI->skillh->skillName(curHero->secSkills[v].first), (v%2) ? 212 : 68, 300 + 48 * (v/2), FONT_SMALL, Colors::WHITE, to);
 	}
 
 	//printing special ability

+ 4 - 3
client/windows/CKingdomInterface.cpp

@@ -28,6 +28,7 @@
 #include "../../lib/CGeneralTextHandler.h"
 #include "../../lib/CHeroHandler.h"
 #include "../../lib/CModHandler.h"
+#include "../../lib/CSkillHandler.h"
 #include "../../lib/CTownHandler.h"
 #include "../../lib/mapObjects/CGHeroInstance.h"
 #include "../../lib/mapObjects/CGTownInstance.h"
@@ -170,7 +171,7 @@ std::string InfoBoxAbstractHeroData::getNameText()
 		return CGI->heroh->heroes[getSubID()]->specName;
 	case HERO_SECONDARY_SKILL:
 		if (getValue())
-			return CGI->generaltexth->skillName[getSubID()];
+			return CGI->skillh->skillName(getSubID());
 		else
 			return "";
 	default:
@@ -281,7 +282,7 @@ bool InfoBoxAbstractHeroData::prepareMessage(std::string &text, CComponent **com
 			if (!value)
 				return false;
 
-			text = CGI->skillInfo(subID,value);
+			text = CGI->skillh->skillInfo(subID, value);
 			*comp = new CComponent(CComponent::secskill, subID, value);
 			return true;
 		}
@@ -356,7 +357,7 @@ std::string InfoBoxHeroData::getHoverText()
 		if (hero->secSkills.size() > index)
 		{
 			std::string level = CGI->generaltexth->levels[hero->secSkills[index].second-1];
-			std::string skill = CGI->generaltexth->skillName[hero->secSkills[index].first];
+			std::string skill = CGI->skillh->skillName(hero->secSkills[index].first);
 			return boost::str(boost::format(CGI->generaltexth->heroscrn[21]) % level % skill);
 		}
 		else

+ 10 - 9
client/windows/GUIClasses.cpp

@@ -49,6 +49,7 @@
 #include "../lib/CHeroHandler.h"
 #include "../lib/CModHandler.h"
 #include "../lib/CondSh.h"
+#include "../lib/CSkillHandler.h"
 #include "../lib/spells/CSpellHandler.h"
 #include "../lib/CStopWatch.h"
 #include "../lib/CTownHandler.h"
@@ -944,11 +945,11 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
 
 			secSkillAreas[b][g]->type = skill;
 			secSkillAreas[b][g]->bonusValue = level;
-			secSkillAreas[b][g]->text = CGI->skillInfo(skill,level);
+			secSkillAreas[b][g]->text = CGI->skillh->skillInfo(skill, level);
 
 			secSkillAreas[b][g]->hoverText = CGI->generaltexth->heroscrn[21];
 			boost::algorithm::replace_first(secSkillAreas[b][g]->hoverText, "%s", CGI->generaltexth->levels[level - 1]);
-			boost::algorithm::replace_first(secSkillAreas[b][g]->hoverText, "%s", CGI->generaltexth->skillName[skill]);
+			boost::algorithm::replace_first(secSkillAreas[b][g]->hoverText, "%s", CGI->skillh->skillName(skill));
 		}
 
 		portrait[b] = new CHeroArea(257 + 228*b, 13, heroInst[b]);
@@ -1222,7 +1223,7 @@ void CUniversityWindow::CItem::clickRight(tribool down, bool previousState)
 {
 	if(down)
 	{
-		CRClickPopup::createAndPush(CGI->skillInfo(ID, 1),
+		CRClickPopup::createAndPush(CGI->skillh->skillInfo(ID, 1),
 				new CComponent(CComponent::secskill, ID, 1));
 	}
 }
@@ -1230,7 +1231,7 @@ void CUniversityWindow::CItem::clickRight(tribool down, bool previousState)
 void CUniversityWindow::CItem::hover(bool on)
 {
 	if (on)
-		GH.statusbar->setText(CGI->generaltexth->skillName[ID]);
+		GH.statusbar->setText(CGI->skillh->skillName(ID));
 	else
 		GH.statusbar->clear();
 }
@@ -1264,7 +1265,7 @@ void CUniversityWindow::CItem::showAll(SDL_Surface * to)
 
 	blitAtLoc(bar->bg, -28, -22, to);
 	blitAtLoc(bar->bg, -28,  48, to);
-	printAtMiddleLoc  (CGI->generaltexth->skillName[ID], 22, -13, FONT_SMALL, Colors::WHITE,to);//Name
+	printAtMiddleLoc  (CGI->skillh->skillName(ID), 22, -13, FONT_SMALL, Colors::WHITE,to);//Name
 	printAtMiddleLoc  (CGI->generaltexth->levels[0], 22, 57, FONT_SMALL, Colors::WHITE,to);//Level(always basic)
 
 	CAnimImage::showAll(to);
@@ -1328,12 +1329,12 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bo
 
 	std::string text = CGI->generaltexth->allTexts[608];
 	boost::replace_first(text, "%s", CGI->generaltexth->levels[0]);
-	boost::replace_first(text, "%s", CGI->generaltexth->skillName[SKILL]);
+	boost::replace_first(text, "%s", CGI->skillh->skillName(SKILL));
 	boost::replace_first(text, "%d", "2000");
 
 	new CTextBox(text, Rect(24, 129, 413, 70), 0, FONT_SMALL, CENTER, Colors::WHITE);//Clerk speech
 
-	new CLabel(230, 37,  FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth-> skillName[SKILL]);//Skill name
+	new CLabel(230, 37,  FONT_SMALL, CENTER, Colors::WHITE, CGI->skillh->skillName(SKILL));//Skill name
 	new CAnimImage("SECSKILL", SKILL*3+3, 0, 211, 51);//skill
 	new CLabel(230, 107, FONT_SMALL, CENTER, Colors::WHITE, CGI->generaltexth->levels[1]);//Skill level
 
@@ -1341,11 +1342,11 @@ CUnivConfirmWindow::CUnivConfirmWindow(CUniversityWindow * PARENT, int SKILL, bo
 	new CLabel(230, 267, FONT_SMALL, CENTER, Colors::WHITE, "2000");//Cost
 
 	std::string hoverText = CGI->generaltexth->allTexts[609];
-	boost::replace_first(hoverText, "%s", CGI->generaltexth->levels[0]+ " " + CGI->generaltexth->skillName[SKILL]);
+	boost::replace_first(hoverText, "%s", CGI->generaltexth->levels[0]+ " " + CGI->skillh->skillName(SKILL));
 
 	text = CGI->generaltexth->zelp[633].second;
 	boost::replace_first(text, "%s", CGI->generaltexth->levels[0]);
-	boost::replace_first(text, "%s", CGI->generaltexth->skillName[SKILL]);
+	boost::replace_first(text, "%s", CGI->skillh->skillName(SKILL));
 	boost::replace_first(text, "%d", "2000");
 
 	confirm= new CButton(Point(148, 299), "IBY6432.DEF", CButton::tooltip(hoverText, text), [=](){makeDeal(SKILL);}, SDLK_RETURN);

+ 0 - 27
config/skills.json

@@ -1,7 +1,6 @@
 {
 	"pathfinding" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.pathfinding",
@@ -28,7 +27,6 @@
 	},
 	"archery" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.archery",
@@ -55,7 +53,6 @@
 	},
 	"logistics" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.logistics",
@@ -82,7 +79,6 @@
 	},
 	"scouting" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"type" : "SIGHT_RADIOUS",
@@ -108,7 +104,6 @@
 	},
 	"diplomacy" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.diplomacy",
@@ -143,7 +138,6 @@
 	},
 	"navigation" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.navigation",
@@ -170,7 +164,6 @@
 	},
 	"leadership" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"type" : "MORALE",
@@ -196,7 +189,6 @@
 	},
 	"wisdom" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.wisdom",
@@ -223,7 +215,6 @@
 	},
 	"mysticism" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"type" : "MANA_REGENERATION",
@@ -249,7 +240,6 @@
 	},
 	"luck" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"type" : "LUCK",
@@ -275,7 +265,6 @@
 	},
 	"ballistics" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.ballistics",
@@ -308,7 +297,6 @@
 	},
 	"eagleEye" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.eagleEye",
@@ -343,7 +331,6 @@
 	},
 	"necromancy" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.necromancy",
@@ -399,7 +386,6 @@
 	},
 	"fireMagic" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.fireMagic",
@@ -426,7 +412,6 @@
 	},
 	"airMagic" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.airMagic",
@@ -453,7 +438,6 @@
 	},
 	"waterMagic" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.waterMagic",
@@ -480,7 +464,6 @@
 	},
 	"earthMagic" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.earthMagic",
@@ -507,7 +490,6 @@
 	},
 	"scholar" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.scholar",
@@ -534,7 +516,6 @@
 	},
 	"tactics" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.tactics",
@@ -561,7 +542,6 @@
 	},
 	"artillery" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.artillery",
@@ -602,7 +582,6 @@
 	},
 	"learning" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.learning",
@@ -629,7 +608,6 @@
 	},
 	"offence" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.offence",
@@ -656,7 +634,6 @@
 	},
 	"armorer" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.armorer",
@@ -683,7 +660,6 @@
 	},
 	"intelligence" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.intelligence",
@@ -710,7 +686,6 @@
 	},
 	"sorcery" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.sorcery",
@@ -737,7 +712,6 @@
 	},
 	"resistance" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.resistance",
@@ -764,7 +738,6 @@
 	},
 	"firstAid" : {
 		"base" : {
-			"description" : "",
 			"effects" : {
 				"main" : {
 					"subtype" : "skill.firstAid",

+ 5 - 3
lib/CGameState.cpp

@@ -20,6 +20,7 @@
 #include "CHeroHandler.h"
 #include "mapObjects/CObjectHandler.h"
 #include "CModHandler.h"
+#include "CSkillHandler.h"
 #include "mapping/CMap.h"
 #include "mapping/CMapService.h"
 #include "StartInfo.h"
@@ -113,6 +114,10 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 	{
 		dst = VLC->objtypeh->getObjectName(ser);
 	}
+	else if(type == SEC_SKILL_NAME)
+	{
+		dst = VLC->skillh->skillName(ser);
+	}
 	else
 	{
 		std::vector<std::string> *vec;
@@ -139,9 +144,6 @@ void MetaString::getLocalString(const std::pair<ui8,ui32> &txt, std::string &dst
 		case ADVOB_TXT:
 			vec = &VLC->generaltexth->advobtxt;
 			break;
-		case SEC_SKILL_NAME:
-			vec = &VLC->generaltexth->skillName;
-			break;
 		case COLOR:
 			vec = &VLC->generaltexth->capColors;
 			break;

+ 0 - 17
lib/CGeneralTextHandler.cpp

@@ -377,23 +377,6 @@ CGeneralTextHandler::CGeneralTextHandler()
 		}
 		while (parser.endLine());
 	}
-	{
-		CLegacyConfigParser parser("DATA/SSTRAITS.TXT");
-
-		//skip header
-		parser.endLine();
-		parser.endLine();
-
-		do
-		{
-			skillName.push_back(parser.readString());
-
-			skillInfoTexts.push_back(std::vector<std::string>());
-			for(int j = 0; j < 3; j++)
-				skillInfoTexts.back().push_back(parser.readString());
-		}
-		while (parser.endLine());
-	}
 	{
 		CLegacyConfigParser parser("DATA/SEERHUT.TXT");
 

+ 0 - 2
lib/CGeneralTextHandler.h

@@ -130,8 +130,6 @@ public:
 	std::vector<std::string> tentColors;
 
 	//sec skills
-	std::vector<std::string> skillName;
-	std::vector<std::vector<std::string>> skillInfoTexts; //[id][level] : level 0 - basic; 2 - advanced
 	std::vector<std::string> levels;
 	std::vector<std::string> zcrexp; //more or less useful content of that file
 	//commanders

+ 37 - 6
lib/CSkillHandler.cpp

@@ -35,7 +35,7 @@ CSkill::LevelInfo::~LevelInfo()
 {
 }
 
-CSkill::CSkill(SecondarySkill id) : id(id)
+CSkill::CSkill(SecondarySkill id) : id(id), name("")
 {
 	if(id == SecondarySkill::DEFAULT)
 		identifier = "default";
@@ -113,24 +113,41 @@ CSkillHandler::CSkillHandler()
 
 std::vector<JsonNode> CSkillHandler::loadLegacyData(size_t dataSize)
 {
+	CLegacyConfigParser parser("DATA/SSTRAITS.TXT");
+
+	//skip header
+	parser.endLine();
+	parser.endLine();
+
+	std::vector<std::string> skillNames;
+	std::vector<std::vector<std::string>> skillInfoTexts;
+	do
+	{
+		skillNames.push_back(parser.readString());
+		skillInfoTexts.push_back(std::vector<std::string>());
+		for(int i = 0; i < 3; i++)
+			skillInfoTexts.back().push_back(parser.readString());
+	}
+	while (parser.endLine());
+
+	assert(skillNames.size() == GameConstants::SKILL_QUANTITY);
+
+	//store & construct JSON
 	std::vector<JsonNode> legacyData;
-	/* problem: CGI is client-side only
 	for(int id = 0; id < GameConstants::SKILL_QUANTITY; id++)
 	{
 		CSkill & skill = *objects[id];
 		JsonNode skillNode(JsonNode::DATA_STRUCT);
 		for(int level = 1; level < NSecondarySkill::levels.size(); level++)
 		{
-			//only "real" legacy data is skill description
-			std::string desc = CGI->generaltexth->skillInfoTexts[skill.id][level-1];
-			//update both skill & JSON
+			skill.name = skillNames[id];
+			std::string & desc = skillInfoTexts[id][level-1];
 			skill.setDescription(desc, level);
 			auto & levelNode = skillNode[NSecondarySkill::levels[level]].Struct();
 			levelNode["description"].String() = desc;
 		}
 		legacyData.push_back(skillNode);
 	}
-	*/
 	return legacyData;
 }
 
@@ -139,6 +156,16 @@ const std::string CSkillHandler::getTypeName() const
 	return "skill";
 }
 
+const std::string & CSkillHandler::skillInfo(int skill, int level) const
+{
+	return objects[skill]->getDescription(level);
+}
+
+const std::string & CSkillHandler::skillName(int skill) const
+{
+	return objects[skill]->name;
+}
+
 CSkill * CSkillHandler::loadFromJson(const JsonNode & json, const std::string & identifier)
 {
 	CSkill * skill = nullptr;
@@ -148,6 +175,8 @@ CSkill * CSkillHandler::loadFromJson(const JsonNode & json, const std::string &
 		if(NSecondarySkill::names[id].compare(identifier) == 0)
 		{
 			skill = new CSkill(SecondarySkill(id));
+			//skill name isn't stored in JSON
+			skill->name = objects[id]->name;
 			break;
 		}
 	}
@@ -172,6 +201,8 @@ CSkill * CSkillHandler::loadFromJson(const JsonNode & json, const std::string &
 		// parse skill description - tracked separately
 		if(vstd::contains(levelNode.Struct(), "description") && !levelNode["description"].isNull())
 			skill->setDescription(levelNode["description"].String(), level);
+		else
+			skill->setDescription(skillInfo(skill->id, level), level);
 	}
 	logMod->debug("loaded secondary skill %s(%d)", identifier, (int)skill->id);
 	logMod->trace("%s", skill->toString());

+ 5 - 0
lib/CSkillHandler.h

@@ -45,11 +45,13 @@ public:
 
 	SecondarySkill id;
 	std::string identifier;
+	std::string name; //as displayed in GUI
 
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & id;
 		h & identifier;
+		h & name;
 		h & levels;
 	}
 
@@ -74,6 +76,9 @@ public:
 	void loadObject(std::string scope, std::string name, const JsonNode & data) override;
 	void loadObject(std::string scope, std::string name, const JsonNode & data, size_t index) override;
 
+	const std::string & skillInfo(int skill, int level) const;
+	const std::string & skillName(int skill) const;
+
 	template <typename Handler> void serialize(Handler & h, const int version)
 	{
 		h & objects;

+ 2 - 1
lib/HeroBonus.cpp

@@ -17,6 +17,7 @@
 #include "CCreatureSet.h"
 #include "CHeroHandler.h"
 #include "CGeneralTextHandler.h"
+#include "CSkillHandler.h"
 #include "CStack.h"
 #include "CArtHandler.h"
 
@@ -1078,7 +1079,7 @@ std::string Bonus::Description() const
 			str << VLC->creh->creatures[sid]->namePl;
 			break;
 		case SECONDARY_SKILL:
-			str << VLC->generaltexth->skillName[sid]/* << " secondary skill"*/;
+			str << VLC->skillh->skillName(sid);
 			break;
 		default:
 			//todo: handle all possible sources

+ 2 - 1
lib/mapObjects/MiscObjects.cpp

@@ -17,6 +17,7 @@
 #include "../CSoundBase.h"
 #include "../CModHandler.h"
 #include "../CHeroHandler.h"
+#include "../CSkillHandler.h"
 #include "CObjectClassesHandler.h"
 #include "../spells/CSpellHandler.h"
 #include "../IGameCallback.h"
@@ -1476,7 +1477,7 @@ std::string CGWitchHut::getHoverText(PlayerColor player) const
 	if(wasVisited(player))
 	{
 		hoverName += "\n" + VLC->generaltexth->allTexts[356]; // + (learn %s)
-		boost::algorithm::replace_first(hoverName,"%s",VLC->generaltexth->skillName[ability]);
+		boost::algorithm::replace_first(hoverName, "%s", VLC->skillh->skillName(ability));
 	}
 	return hoverName;
 }