瀏覽代碼

CSecSkillPlace done

SoundSSGood 1 年之前
父節點
當前提交
83279211e6

+ 2 - 0
client/widgets/CArtifactsOfHeroAltar.cpp

@@ -22,6 +22,8 @@
 CArtifactsOfHeroAltar::CArtifactsOfHeroAltar(const Point & position)
 {
 	init(position, std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
+	setClickPrassedArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
+	setShowPopupArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2));
 	enableGesture();
 	// The backpack is in the altar window above and to the right
 	for(auto & slot : backpack)

+ 4 - 2
client/widgets/CArtifactsOfHeroBackpack.cpp

@@ -40,6 +40,8 @@ CArtifactsOfHeroBackpack::CArtifactsOfHeroBackpack()
 		visibleCapacityMax = visibleCapacityMax > backpackCap ? backpackCap : visibleCapacityMax;
 
 	initAOHbackpack(visibleCapacityMax, backpackCap < 0 || visibleCapacityMax < backpackCap);
+	setClickPrassedArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
+	setShowPopupArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2));
 }
 
 void CArtifactsOfHeroBackpack::onSliderMoved(int newVal)
@@ -84,8 +86,6 @@ void CArtifactsOfHeroBackpack::initAOHbackpack(size_t slots, bool slider)
 		backpackSlotsBackgrounds.emplace_back(std::make_shared<CPicture>(ImagePath::builtin("heroWindow/artifactSlotEmpty"), pos));
 		artPlace = std::make_shared<CArtPlace>(pos);
 		artPlace->setArtifact(ArtifactID(ArtifactID::NONE));
-		artPlace->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
-		artPlace->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2));
 		artPlaceIdx++;
 	}
 
@@ -130,6 +130,7 @@ CArtifactsOfHeroQuickBackpack::CArtifactsOfHeroQuickBackpack(const ArtifactPosit
 		return;
 
 	this->filterBySlot = filterBySlot;
+	setShowPopupArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2));
 }
 
 void CArtifactsOfHeroQuickBackpack::setHero(const CGHeroInstance * hero)
@@ -172,6 +173,7 @@ void CArtifactsOfHeroQuickBackpack::setHero(const CGHeroInstance * hero)
 		slotsColumnsMax = ceilf(sqrtf(requiredSlots));
 		slotsRowsMax = calcRows(requiredSlots);
 		initAOHbackpack(requiredSlots, false);
+		setClickPrassedArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
 		auto artPlace = backpack.begin();
 		for(auto & art : filteredArts)
 			setSlotData(*artPlace++, curHero->getArtPos(art.second));

+ 22 - 16
client/widgets/CArtifactsOfHeroBase.cpp

@@ -63,18 +63,14 @@ void CArtifactsOfHeroBase::init(
 		auto artPlace = std::make_shared<CArtPlace>(Point(403 + 46 * s, 365));
 		backpack.push_back(artPlace);
 	}
-	for(auto artPlace : artWorn)
+	for(auto & artPlace : artWorn)
 	{
 		artPlace.second->slot = artPlace.first;
 		artPlace.second->setArtifact(ArtifactID(ArtifactID::NONE));
-		artPlace.second->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
-		artPlace.second->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2));
 	}
-	for(auto artPlace : backpack)
+	for(const auto & artPlace : backpack)
 	{
 		artPlace->setArtifact(ArtifactID(ArtifactID::NONE));
-		artPlace->setClickPressedCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
-		artPlace->setShowPopupCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2));
 	}
 	leftBackpackRoll = std::make_shared<CButton>(Point(379, 364), AnimationPath::builtin("hsbtns3.def"), CButton::tooltip(),
 		[scrollCallback](){scrollCallback(true);}, EShortcut::MOVE_LEFT);
@@ -89,6 +85,22 @@ void CArtifactsOfHeroBase::init(
 	setRedrawParent(true);
 }
 
+void CArtifactsOfHeroBase::setClickPrassedArtPlacesCallback(const CArtPlace::ClickFunctor & callback) const
+{
+	for(const auto & [slot, artPlace] : artWorn)
+		artPlace->setClickPressedCallback(callback);
+	for(const auto & artPlace : backpack)
+		artPlace->setClickPressedCallback(callback);
+}
+
+void CArtifactsOfHeroBase::setShowPopupArtPlacesCallback(const CArtPlace::ClickFunctor & callback) const
+{
+	for(const auto & [slot, artPlace] : artWorn)
+		artPlace->setShowPopupCallback(callback);
+	for(const auto & artPlace : backpack)
+		artPlace->setShowPopupCallback(callback);
+}
+
 void CArtifactsOfHeroBase::clickPrassedArtPlace(CComponentHolder & artPlace, const Point & cursorPosition)
 {
 	auto ownedPlace = getArtPlace(cursorPosition);
@@ -163,16 +175,10 @@ void CArtifactsOfHeroBase::unmarkSlots()
 
 CArtifactsOfHeroBase::ArtPlacePtr CArtifactsOfHeroBase::getArtPlace(const ArtifactPosition & slot)
 {
-	if(ArtifactUtils::isSlotEquipment(slot))
-	{
-		if(artWorn.find(slot) != artWorn.end())
-			return artWorn[slot];
-	}
-	if(ArtifactUtils::isSlotBackpack(slot))
-	{
-		if(slot - ArtifactPosition::BACKPACK_START < backpack.size())
-			return(backpack[slot - ArtifactPosition::BACKPACK_START]);
-	}
+	if(ArtifactUtils::isSlotEquipment(slot) && artWorn.find(slot) != artWorn.end())
+		return artWorn[slot];
+	if(ArtifactUtils::isSlotBackpack(slot) && slot - ArtifactPosition::BACKPACK_START < backpack.size())
+		return(backpack[slot - ArtifactPosition::BACKPACK_START]);
 	logGlobal->error("CArtifactsOfHero::getArtPlace: invalid slot %d", slot);
 	return nullptr;
 }

+ 2 - 0
client/widgets/CArtifactsOfHeroBase.h

@@ -50,6 +50,8 @@ public:
 	void enableGesture();
 	const CArtifactInstance * getArt(const ArtifactPosition & slot) const;
 	void enableKeyboardShortcuts();
+	void setClickPrassedArtPlacesCallback(const CArtPlace::ClickFunctor & callback) const;
+	void setShowPopupArtPlacesCallback(const CArtPlace::ClickFunctor & callback) const;
 
 	const CGHeroInstance * curHero;
 	ArtPlaceMap artWorn;

+ 2 - 0
client/widgets/CArtifactsOfHeroMain.cpp

@@ -21,6 +21,8 @@
 CArtifactsOfHeroMain::CArtifactsOfHeroMain(const Point & position)
 {
 	init(position, std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
+	setClickPrassedArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
+	setShowPopupArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::showPopupArtPlace, this, _1, _2));
 	enableGesture();
 }
 

+ 1 - 1
client/widgets/CArtifactsOfHeroMarket.cpp

@@ -15,7 +15,7 @@
 CArtifactsOfHeroMarket::CArtifactsOfHeroMarket(const Point & position, const int selectionWidth)
 {
 	init(position, std::bind(&CArtifactsOfHeroBase::scrollBackpack, this, _1));
-
+	setClickPrassedArtPlacesCallback(std::bind(&CArtifactsOfHeroBase::clickPrassedArtPlace, this, _1, _2));
 	for(const auto & [slot, artPlace] : artWorn)
 		artPlace->setSelectionWidth(selectionWidth);
 	for(auto artPlace : backpack)

+ 58 - 11
client/widgets/CComponentHolder.cpp

@@ -33,6 +33,16 @@
 CComponentHolder::CComponentHolder(const Rect & area, const Point & selectionOversize)
 	: SelectableSlot(area, selectionOversize)
 {
+	setClickPressedCallback([this](const CComponentHolder &, const Point & cursorPosition)
+		{
+			if(text.size())
+				LRClickableAreaWTextComp::clickPressed(cursorPosition);
+		});
+	setShowPopupCallback([this](const CComponentHolder &, const Point & cursorPosition)
+		{
+			if(text.size())
+				LRClickableAreaWTextComp::showPopupWindow(cursorPosition);
+		});
 }
 
 void CComponentHolder::setClickPressedCallback(const ClickFunctor & callback)
@@ -83,14 +93,14 @@ CArtPlace::CArtPlace(Point position, const ArtifactID & artId, const SpellID & s
 	moveSelectionForeground();
 }
 
-void CArtPlace::setArtifact(const SpellID & spellId)
+void CArtPlace::setArtifact(const SpellID & newSpellId)
 {
-	setArtifact(ArtifactID::SPELL_SCROLL, spellId);
+	setArtifact(ArtifactID::SPELL_SCROLL, newSpellId);
 }
 
-void CArtPlace::setArtifact(const ArtifactID & artId, const SpellID & spellId)
+void CArtPlace::setArtifact(const ArtifactID & newArtId, const SpellID & newSpellId)
 {
-	this->artId = artId;
+	artId = newArtId;
 	if(artId == ArtifactID::NONE)
 	{
 		image->disable();
@@ -103,7 +113,7 @@ void CArtPlace::setArtifact(const ArtifactID & artId, const SpellID & spellId)
 	imageIndex = artType->getIconIndex();
 	if(artId == ArtifactID::SPELL_SCROLL)
 	{
-		this->spellId = spellId;
+		spellId = newSpellId;
 		assert(spellId.num > 0);
 
 		if(settings["general"]["enableUiEnhancements"].Bool())
@@ -251,16 +261,53 @@ void CArtPlace::addCombinedArtInfo(const std::map<const ArtifactID, std::vector<
 	}
 }
 
-CSecSkillPlace::CSecSkillPlace(const Point & position, const SecondarySkill & skillId)
-	: CComponentHolder(Rect(position, Point(44, 44)), Point())
+CSecSkillPlace::CSecSkillPlace(const Point & position, const ImageSize & imageSize, const SecondarySkill & newSkillId, const uint8_t level)
+	: CComponentHolder(Rect(position, Point()), Point())
 {
 	OBJECT_CONSTRUCTION;
 
-	image = std::make_shared<CAnimImage>(AnimationPath::builtin("SECSKILL"), 0);
-	setSkill(skillId);
+	auto imagePath = AnimationPath::builtin("SECSKILL");
+	if(imageSize == ImageSize::MEDIUM)
+		imagePath = AnimationPath::builtin("SECSK32");
+	if(imageSize == ImageSize::SMALL)
+		imagePath = AnimationPath::builtin("SECSK82");
+
+	image = std::make_shared<CAnimImage>(imagePath, 0);
+	component.type = ComponentType::SEC_SKILL;
+	pos.w = image->pos.w;
+	pos.h = image->pos.h;
+	setSkill(newSkillId, level);
 }
 
-void CSecSkillPlace::setSkill(const SecondarySkill & skillId)
+void CSecSkillPlace::setSkill(const SecondarySkill & newSkillId, const uint8_t level)
 {
-	//skillId.toSkill()->getIconIndex();
+	skillId = newSkillId;
+	component.subType = newSkillId;
+	setLevel(level);
+}
+
+void CSecSkillPlace::setLevel(const uint8_t level)
+{
+	// 0 - none
+	// 1 - base
+	// 2 - advanced
+	// 3 - expert
+	assert(level <= 3);
+	if(skillId != SecondarySkill::NONE && level > 0)
+	{
+		image->setFrame(skillId.toSkill()->getIconIndex() + level - 1);
+		image->enable();
+		auto hoverText = MetaString::createFromRawString(CGI->generaltexth->heroscrn[21]);
+		hoverText.replaceRawString(CGI->generaltexth->levels[level - 1]);
+		hoverText.replaceTextID(SecondarySkill(skillId).toSkill()->getNameTextID());
+		this->hoverText = hoverText.toString();
+		component.value = level;
+		text = CGI->skillh->getByIndex(skillId)->getDescriptionTranslated(level);
+	}
+	else
+	{
+		image->disable();
+		hoverText.clear();
+		text.clear();
+	}
 }

+ 13 - 6
client/widgets/CComponentHolder.h

@@ -30,7 +30,6 @@ public:
 	void clickPressed(const Point & cursorPosition) override;
 	void showPopupWindow(const Point & cursorPosition) override;
 	void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
-	virtual ~CComponentHolder() = default;
 };
 
 class CArtPlace : public CComponentHolder
@@ -38,9 +37,9 @@ class CArtPlace : public CComponentHolder
 public:
 	ArtifactPosition slot;
 	
-	CArtPlace(Point position, const ArtifactID & artId = ArtifactID::NONE, const SpellID & spellId = SpellID::NONE);
-	void setArtifact(const SpellID & spellId);
-	void setArtifact(const ArtifactID & artId, const SpellID & spellId = SpellID::NONE);
+	CArtPlace(Point position, const ArtifactID & newArtId = ArtifactID::NONE, const SpellID & newSpellId = SpellID::NONE);
+	void setArtifact(const SpellID & newSpellId);
+	void setArtifact(const ArtifactID & newArtId, const SpellID & newSpellId = SpellID::NONE);
 	ArtifactID getArtifactId() const;
 	void lockSlot(bool on);
 	bool isLocked() const;
@@ -71,8 +70,16 @@ public:
 class CSecSkillPlace : public CComponentHolder
 {
 public:
-	CSecSkillPlace(const Point & position, const SecondarySkill & skillId = SecondarySkill::NONE);
-	void setSkill(const SecondarySkill & skillId);
+	enum class ImageSize
+	{
+		LARGE,
+		MEDIUM,
+		SMALL
+	};
+
+	CSecSkillPlace(const Point & position, const ImageSize & imageSize, const SecondarySkill & skillId = SecondarySkill::NONE, const uint8_t level = 0);
+	void setSkill(const SecondarySkill & newSkillId, const uint8_t level = 0);
+	void setLevel(const uint8_t level);
 
 private:
 	SecondarySkill skillId;

+ 1 - 1
client/widgets/markets/CAltarCreatures.cpp

@@ -162,7 +162,7 @@ void CAltarCreatures::makeDeal()
 	for(int & units : unitsOnAltar)
 		units = 0;
 
-	for(auto & heroSlot : offerTradePanel->slots)
+	for(const auto & heroSlot : offerTradePanel->slots)
 	{
 		heroSlot->setID(CreatureID::NONE);
 		heroSlot->subtitle->clear();

+ 3 - 17
client/windows/CExchangeWindow.cpp

@@ -82,7 +82,8 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
 
 
 		for(int m=0; m < hero->secSkills.size(); ++m)
-			secSkillIcons[leftRight].push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SECSK32"), 0, 0, 32 + 36 * m + 454 * leftRight, qeLayout ? 83 : 88));
+			secSkills[leftRight].push_back(std::make_shared<CSecSkillPlace>(Point(32 + 36 * m + 454 * leftRight, qeLayout ? 83 : 88), CSecSkillPlace::ImageSize::MEDIUM,
+				hero->secSkills[m].first, hero->secSkills[m].second));
 
 		specImages[leftRight] = std::make_shared<CAnimImage>(AnimationPath::builtin("UN32"), hero->getHeroType()->imageIndex, 0, 67 + 490 * leftRight, qeLayout ? 41 : 45);
 
@@ -126,21 +127,6 @@ CExchangeWindow::CExchangeWindow(ObjectInstanceID hero1, ObjectInstanceID hero2,
 	{
 		const CGHeroInstance * hero = heroInst.at(b);
 
-		//secondary skill's clickable areas
-		for(int g=0; g<hero->secSkills.size(); ++g)
-		{
-			SecondarySkill skill = hero->secSkills[g].first;
-			int level = hero->secSkills[g].second; // <1, 3>
-			secSkillAreas[b].push_back(std::make_shared<LRClickableAreaWTextComp>());
-			secSkillAreas[b][g]->pos = Rect(Point(pos.x + 32 + g * 36 + b * 454 , pos.y + (qeLayout ? 83 : 88)), Point(32, 32) );
-			secSkillAreas[b][g]->component = Component(ComponentType::SEC_SKILL, skill, level);
-			secSkillAreas[b][g]->text = CGI->skillh->getByIndex(skill)->getDescriptionTranslated(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->skillh->getByIndex(skill)->getNameTranslated());
-		}
-
 		heroAreas[b] = std::make_shared<CHeroArea>(257 + 228 * b, 13, hero);
 		heroAreas[b]->addClickCallback([this, hero]() -> void
 									   {
@@ -362,7 +348,7 @@ void CExchangeWindow::update()
 			int id = hero->secSkills[m].first;
 			int level = hero->secSkills[m].second;
 
-			secSkillIcons[leftRight][m]->setFrame(2 + id * 3 + level);
+			secSkills[leftRight][m]->setSkill(id, level);
 		}
 
 		expValues[leftRight]->setText(TextOperations::formatMetric(hero->exp, 3));

+ 1 - 2
client/windows/CExchangeWindow.h

@@ -19,7 +19,6 @@ class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public
 	std::array<std::shared_ptr<CLabel>, 2> titles;
 	std::vector<std::shared_ptr<CAnimImage>> primSkillImages;//shared for both heroes
 	std::array<std::vector<std::shared_ptr<CLabel>>, 2> primSkillValues;
-	std::array<std::vector<std::shared_ptr<CAnimImage>>, 2> secSkillIcons;
 	std::array<std::shared_ptr<CAnimImage>, 2> specImages;
 	std::array<std::shared_ptr<CAnimImage>, 2> expImages;
 	std::array<std::shared_ptr<CLabel>, 2> expValues;
@@ -27,7 +26,7 @@ class CExchangeWindow : public CStatusbarWindow, public IGarrisonHolder, public
 	std::array<std::shared_ptr<CLabel>, 2> manaValues;
 
 	std::vector<std::shared_ptr<LRClickableAreaWTextComp>> primSkillAreas;
-	std::array<std::vector<std::shared_ptr<LRClickableAreaWTextComp>>, 2> secSkillAreas;
+	std::array<std::vector<std::shared_ptr<CSecSkillPlace>>, 2> secSkills;
 
 	std::array<std::shared_ptr<CHeroArea>, 2> heroAreas;
 	std::array<std::shared_ptr<LRClickableAreaWText>, 2> specialtyAreas;

+ 0 - 4
client/windows/CHeroBackpackWindow.cpp

@@ -93,10 +93,6 @@ CHeroQuickBackpackWindow::CHeroQuickBackpackWindow(const CGHeroInstance * hero,
 		if(const auto curHero = arts->getHero())
 			swapArtifactAndClose(*arts, artPlace.slot, ArtifactLocation(curHero->id, arts->getFilterSlot()));
 	};
-	arts->showPopupCallback = [this](CArtPlace & artPlace, const Point & cursorPosition)
-	{
-		showArifactInfo(*arts, artPlace, cursorPosition);
-	};
 	addSet(arts);
 	arts->setHero(hero);
 	addUsedEvents(GESTURE);

+ 3 - 8
client/windows/CHeroWindow.cpp

@@ -152,8 +152,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance * hero)
 	for(int i = 0; i < std::min<size_t>(hero->secSkills.size(), 8u); ++i)
 	{
 		Rect r = Rect(i%2 == 0  ?  18  :  162,  276 + 48 * (i/2),  136,  42);
-		secSkillAreas.push_back(std::make_shared<LRClickableAreaWTextComp>(r, ComponentType::SEC_SKILL));
-		secSkillImages.push_back(std::make_shared<CAnimImage>(AnimationPath::builtin("SECSKILL"), 0, 0, r.x, r.y));
+		secSkills.emplace_back(std::make_shared<CSecSkillPlace>(r.topLeft(), CSecSkillPlace::ImageSize::LARGE));
 
 		int x = (i % 2) ? 212 : 68;
 		int y = 280 + 48 * (i/2);
@@ -234,20 +233,16 @@ void CHeroWindow::update()
 	}
 
 	//secondary skills support
-	for(size_t g=0; g< secSkillAreas.size(); ++g)
+	for(size_t g=0; g< secSkills.size(); ++g)
 	{
 		SecondarySkill skill = curHero->secSkills[g].first;
 		int	level = curHero->getSecSkillLevel(skill);
 		std::string skillName = CGI->skillh->getByIndex(skill)->getNameTranslated();
 		std::string skillValue = CGI->generaltexth->levels[level-1];
 
-		secSkillAreas[g]->component.subType = skill;
-		secSkillAreas[g]->component.value = level;
-		secSkillAreas[g]->text = CGI->skillh->getByIndex(skill)->getDescriptionTranslated(level);
-		secSkillAreas[g]->hoverText = boost::str(boost::format(heroscrn[21]) % skillValue % skillName);
-		secSkillImages[g]->setFrame(skill*3 + level + 2);
 		secSkillNames[g]->setText(skillName);
 		secSkillValues[g]->setText(skillValue);
+		secSkills[g]->setSkill(skill, level);
 	}
 
 	std::ostringstream expstr;

+ 1 - 2
client/windows/CHeroWindow.h

@@ -74,8 +74,7 @@ class CHeroWindow : public CStatusbarWindow, public IGarrisonHolder, public CWin
 	std::shared_ptr<CLabel> specName;
 	std::shared_ptr<MoraleLuckBox> morale;
 	std::shared_ptr<MoraleLuckBox> luck;
-	std::vector<std::shared_ptr<LRClickableAreaWTextComp>> secSkillAreas;
-	std::vector<std::shared_ptr<CAnimImage>> secSkillImages;
+	std::vector< std::shared_ptr<CSecSkillPlace>> secSkills;
 	std::vector<std::shared_ptr<CLabel>> secSkillNames;
 	std::vector<std::shared_ptr<CLabel>> secSkillValues;
 

+ 0 - 1
client/windows/CMarketWindow.cpp

@@ -219,7 +219,6 @@ void CMarketWindow::createArtifactsSelling(const IMarket * market, const CGHeroI
 	auto artsSellingMarket = std::make_shared<CArtifactsSelling>(market, hero, getMarketTitle(market->getObjInstanceID(), EMarketMode::ARTIFACT_RESOURCE));
 	artSets.clear();
 	const auto heroArts = artsSellingMarket->getAOHset();
-	heroArts->showPopupCallback = [this, heroArts](CArtPlace & artPlace, const Point & cursorPosition){showArifactInfo(*heroArts, artPlace, cursorPosition);};
 	addSet(heroArts);
 	marketWidget = artsSellingMarket;
 	initWidgetInternals(EMarketMode::ARTIFACT_RESOURCE, CGI->generaltexth->zelp[600]);

+ 0 - 6
client/windows/CWindowWithArtifacts.cpp

@@ -128,12 +128,6 @@ void CWindowWithArtifacts::showArtifactAssembling(const CArtifactsOfHeroBase & a
 	}
 }
 
-void CWindowWithArtifacts::showArifactInfo(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) const
-{
-	if(artsInst.getArt(artPlace.slot) && artPlace.text.size())
-		artPlace.LRClickableAreaWTextComp::showPopupWindow(cursorPosition);
-}
-
 void CWindowWithArtifacts::showQuickBackpackWindow(const CGHeroInstance * hero, const ArtifactPosition & slot,
 	const Point & cursorPosition) const
 {

+ 0 - 1
client/windows/CWindowWithArtifacts.h

@@ -31,7 +31,6 @@ public:
 		bool allowExchange, bool altarTrading, bool closeWindow);
 	void swapArtifactAndClose(const CArtifactsOfHeroBase & artsInst, const ArtifactPosition & slot, const ArtifactLocation & dstLoc);
 	void showArtifactAssembling(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) const;
-	void showArifactInfo(const CArtifactsOfHeroBase & artsInst, CArtPlace & artPlace, const Point & cursorPosition) const;
 	void showQuickBackpackWindow(const CGHeroInstance * hero, const ArtifactPosition & slot, const Point & cursorPosition) const;
 	void activate() override;
 	void deactivate() override;

+ 8 - 26
client/windows/GUIClasses.cpp

@@ -896,28 +896,18 @@ CUniversityWindow::CItem::CItem(CUniversityWindow * _parent, int _ID, int X, int
 	pos.x += X;
 	pos.y += Y;
 
-	icon = std::make_shared<CAnimImage>(AnimationPath::builtin("SECSKILL"), _ID * 3 + 3, 0);
-
-	pos.h = icon->pos.h;
-	pos.w = icon->pos.w;
+	skill = std::make_shared<CSecSkillPlace>(Point(), CSecSkillPlace::ImageSize::LARGE, _ID, 1);
+	skill->setClickPressedCallback([this](const CComponentHolder&, const Point& cursorPosition)
+		{
+			bool skillKnown = parent->hero->getSecSkillLevel(ID);
+			bool canLearn = parent->hero->canLearnSkill(ID);
 
+			if(!skillKnown && canLearn)
+				GH.windows().createAndPushWindow<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) >= 2000);
+		});
 	update();
 }
 
-void CUniversityWindow::CItem::clickPressed(const Point & cursorPosition)
-{
-	bool skillKnown = parent->hero->getSecSkillLevel(ID);
-	bool canLearn =	parent->hero->canLearnSkill(ID);
-
-	if (!skillKnown && canLearn)
-		GH.windows().createAndPushWindow<CUnivConfirmWindow>(parent, ID, LOCPLINT->cb->getResourceAmount(EGameResID::GOLD) >= 2000);
-}
-
-void CUniversityWindow::CItem::showPopupWindow(const Point & cursorPosition)
-{
-	CRClickPopup::createAndPush(CGI->skillh->getByIndex(ID)->getDescriptionTranslated(1), std::make_shared<CComponent>(ComponentType::SEC_SKILL, ID, 1));
-}
-
 void CUniversityWindow::CItem::update()
 {
 	bool skillKnown = parent->hero->getSecSkillLevel(ID);
@@ -941,14 +931,6 @@ void CUniversityWindow::CItem::update()
 	level = std::make_shared<CLabel>(22, 57, FONT_SMALL, ETextAlignment::CENTER, Colors::WHITE, CGI->generaltexth->levels[0]);
 }
 
-void CUniversityWindow::CItem::hover(bool on)
-{
-	if(on)
-		GH.statusbar()->write(ID.toEntity(VLC)->getNameTranslated());
-	else
-		GH.statusbar()->clear();
-}
-
 CUniversityWindow::CUniversityWindow(const CGHeroInstance * _hero, BuildingID building, const IMarket * _market, const std::function<void()> & onWindowClosed)
 	: CWindowObject(PLAYER_COLORED, ImagePath::builtin("UNIVERS1")),
 	hero(_hero),

+ 2 - 4
client/windows/GUIClasses.h

@@ -46,6 +46,7 @@ class VideoWidget;
 class VideoWidgetOnce;
 class GraphicalPrimitiveCanvas;
 class TransparentFilledRectangle;
+class CSecSkillPlace;
 
 enum class EUserEvent;
 
@@ -370,7 +371,7 @@ class CUniversityWindow final : public CStatusbarWindow, public IMarketHolder
 {
 	class CItem final : public CIntObject
 	{
-		std::shared_ptr<CAnimImage> icon;
+		std::shared_ptr<CSecSkillPlace> skill;
 		std::shared_ptr<CPicture> topBar;
 		std::shared_ptr<CPicture> bottomBar;
 		std::shared_ptr<CLabel> name;
@@ -379,9 +380,6 @@ class CUniversityWindow final : public CStatusbarWindow, public IMarketHolder
 		SecondarySkill ID;//id of selected skill
 		CUniversityWindow * parent;
 
-		void clickPressed(const Point & cursorPosition) override;
-		void showPopupWindow(const Point & cursorPosition) override;
-		void hover(bool on) override;
 		void update();
 		CItem(CUniversityWindow * _parent, int _ID, int X, int Y);
 	};

+ 1 - 1
lib/CSkillHandler.cpp

@@ -45,7 +45,7 @@ int32_t CSkill::getIndex() const
 
 int32_t CSkill::getIconIndex() const
 {
-	return getIndex(); //TODO: actual value with skill level
+	return getIndex() * 3 + 3; //TODO: actual value with skill level
 }
 
 std::string CSkill::getNameTextID() const