瀏覽代碼

Merge pull request #4334 from Laserlicht/quickspell_improve

quickspell improvements
Ivan Savenko 1 年之前
父節點
當前提交
3f9e57d3f3

+ 53 - 13
client/battle/BattleInterfaceClasses.cpp

@@ -433,6 +433,50 @@ QuickSpellPanel::QuickSpellPanel(BattleInterface & owner)
 	create();
 }
 
+std::vector<std::tuple<SpellID, bool>> QuickSpellPanel::getSpells()
+{
+	std::vector<SpellID> spellIds;
+	std::vector<bool> spellIdsFromSetting;
+	for(int i = 0; i < QUICKSPELL_SLOTS; i++)
+	{
+		std::string spellIdentifier = persistentStorage["quickSpell"][std::to_string(i)].String();
+		SpellID id;
+		try
+		{
+			id = SpellID::decode(spellIdentifier);
+		}
+		catch(const IdentifierResolutionException& e)
+		{
+			id = SpellID::NONE;
+		}	
+		spellIds.push_back(id);	
+		spellIdsFromSetting.push_back(id != SpellID::NONE);	
+	}
+
+	// autofill empty slots with spells if possible
+	auto hero = owner.getBattle()->battleGetMyHero();
+	for(int i = 0; i < QUICKSPELL_SLOTS; i++)
+	{
+		if(spellIds[i] != SpellID::NONE)
+			continue;
+
+		for(const auto & availableSpellID : CGI->spellh->getDefaultAllowed())
+		{
+			const auto * availableSpell = availableSpellID.toSpell();
+			if(!availableSpell->isAdventure() && !availableSpell->isCreatureAbility() && hero->canCastThisSpell(availableSpell) && !vstd::contains(spellIds, availableSpell->getId()))
+			{
+				spellIds[i] = availableSpell->getId();
+				break;
+			}	
+		}
+	}
+
+	std::vector<std::tuple<SpellID, bool>> ret;
+	for(int i = 0; i < QUICKSPELL_SLOTS; i++)
+		ret.push_back(std::make_tuple(spellIds[i], spellIdsFromSetting[i]));
+	return ret;
+}
+
 void QuickSpellPanel::create()
 {
 	OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
@@ -447,18 +491,11 @@ void QuickSpellPanel::create()
 	if(!hero)
 		return;
 
-	for(int i = 0; i < 12; i++) {
-		std::string spellIdentifier = persistentStorage["quickSpell"][std::to_string(i)].String();
-
+	auto spells = getSpells();
+	for(int i = 0; i < QUICKSPELL_SLOTS; i++) {
 		SpellID id;
-		try
-		{
-			id = SpellID::decode(spellIdentifier);
-		}
-		catch(const IdentifierResolutionException& e)
-		{
-			id = SpellID::NONE;
-		}
+		bool fromSettings;
+		std::tie(id, fromSettings) = spells[i];
 
 		auto button = std::make_shared<CButton>(Point(2, 7 + 50 * i), AnimationPath::builtin("spellint"), CButton::tooltip(), [this, id, hero](){
 			if(id.hasValue() && id.toSpell()->canBeCast(owner.getBattle().get(), spells::Mode::HERO, hero))
@@ -466,16 +503,19 @@ void QuickSpellPanel::create()
 				owner.castThisSpell(id);
 			}
 		});
-		button->setOverlay(std::make_shared<CAnimImage>(AnimationPath::builtin("spellint"), !spellIdentifier.empty() ? id.num + 1 : 0));
+		button->setOverlay(std::make_shared<CAnimImage>(AnimationPath::builtin("spellint"), id != SpellID::NONE ? id.num + 1 : 0));
 		button->addPopupCallback([this, i, hero](){
 			GH.input().hapticFeedback();
 			GH.windows().createAndPushWindow<CSpellWindow>(hero, owner.curInt.get(), true, [this, i](SpellID spell){
 				Settings configID = persistentStorage.write["quickSpell"][std::to_string(i)];
-				configID->String() = spell.toSpell()->identifier;
+				configID->String() = spell == SpellID::NONE ? "" : spell.toSpell()->identifier;
 				create();
 			});
 		});
 
+		if(fromSettings)
+			buttonsIsAutoGenerated.push_back(std::make_shared<TransparentFilledRectangle>(Rect(45, 37 + 50 * i, 5, 5), Colors::ORANGE));
+
 		if(!id.hasValue() || !id.toSpell()->canBeCast(owner.getBattle().get(), spells::Mode::HERO, hero))
 		{
 			buttonsDisabled.push_back(std::make_shared<TransparentFilledRectangle>(Rect(2, 7 + 50 * i, 48, 36), ColorRGBA(0, 0, 0, 172)));

+ 5 - 0
client/battle/BattleInterfaceClasses.h

@@ -155,17 +155,22 @@ private:
 	std::shared_ptr<CFilledTexture> background;
 	std::shared_ptr<TransparentFilledRectangle> rect;
 	std::vector<std::shared_ptr<CButton>> buttons;
+	std::vector<std::shared_ptr<TransparentFilledRectangle>> buttonsIsAutoGenerated;
 	std::vector<std::shared_ptr<TransparentFilledRectangle>> buttonsDisabled;
 	std::vector<std::shared_ptr<CLabel>> labels;
 
 	BattleInterface & owner;
 public:
+	int QUICKSPELL_SLOTS = 12;
+
 	bool isEnabled; // isActive() is not working on multiple conditions, because of this we need a seperate flag
 
 	QuickSpellPanel(BattleInterface & owner);
 
 	void create();
 
+	std::vector<std::tuple<SpellID, bool>> getSpells();
+
 	void show(Canvas & to) override;
 	void inputModeChanged(InputMode modi) override;
 };

+ 5 - 8
client/battle/BattleWindow.cpp

@@ -275,16 +275,13 @@ std::shared_ptr<BattleConsole> BattleWindow::buildBattleConsole(const JsonNode &
 
 void BattleWindow::useSpellIfPossible(int slot)
 {
-	std::string spellIdentifier = persistentStorage["quickSpell"][std::to_string(slot)].String();
 	SpellID id;
-	try
-	{
-		id = SpellID::decode(spellIdentifier);
-	}
-	catch(const IdentifierResolutionException& e)
-	{
+	bool fromSettings;
+	std::tie(id, fromSettings) = quickSpellWindow->getSpells()[slot];
+
+	if(id == SpellID::NONE)
 		return;
-	}
+
 	if(id.hasValue() && owner.getBattle()->battleGetMyHero() && id.toSpell()->canBeCast(owner.getBattle().get(), spells::Mode::HERO, owner.getBattle()->battleGetMyHero()))
 	{
 		owner.castThisSpell(id);

+ 14 - 3
client/windows/CSpellWindow.cpp

@@ -29,6 +29,7 @@
 #include "../widgets/CComponent.h"
 #include "../widgets/CTextInput.h"
 #include "../widgets/TextControls.h"
+#include "../widgets/Buttons.h"
 #include "../adventureMap/AdventureMapInterface.h"
 #include "../render/IRenderHandler.h"
 #include "../render/IImage.h"
@@ -130,9 +131,9 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 
 	pos = background->center(Point(pos.w/2 + pos.x, pos.h/2 + pos.y));
 
+	Rect r(90, isBigSpellbook ? 480 : 420, isBigSpellbook ? 160 : 110, 16);
 	if(settings["general"]["enableUiEnhancements"].Bool())
 	{
-		Rect r(90, isBigSpellbook ? 480 : 420, isBigSpellbook ? 160 : 110, 16);
 		const ColorRGBA rectangleColor = ColorRGBA(0, 0, 0, 75);
 		const ColorRGBA borderColor = ColorRGBA(128, 100, 75);
 		const ColorRGBA grayedColor = ColorRGBA(158, 130, 105);
@@ -143,6 +144,13 @@ CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _m
 		searchBox->setCallback(std::bind(&CSpellWindow::searchInput, this));
 	}
 
+	if(onSpellSelect)
+	{
+		Point boxPos = r.bottomLeft() + Point(-2, 5);
+		showAllSpells = std::make_shared<CToggleButton>(boxPos, AnimationPath::builtin("sysopchk.def"), CButton::tooltip(CGI->generaltexth->translate("core.help.458.hover"), CGI->generaltexth->translate("core.help.458.hover")), [this](bool state){ searchInput(); });
+		showAllSpellsDescription = std::make_shared<CLabel>(boxPos.x + 40, boxPos.y + 12, FONT_SMALL, ETextAlignment::CENTERLEFT, Colors::WHITE, CGI->generaltexth->translate("core.help.458.hover"));
+	}
+
 	processSpells();
 
 	//numbers of spell pages computed
@@ -288,7 +296,7 @@ void CSpellWindow::processSpells()
 
 		if(onSpellSelect)
 		{
-			if(spell->isCombat() == openOnBattleSpells && !spell->isSpecial() && !spell->isCreatureAbility() && searchTextFound)
+			if(spell->isCombat() == openOnBattleSpells && !spell->isSpecial() && !spell->isCreatureAbility() && searchTextFound && (showAllSpells->isSelected() || myHero->canCastThisSpell(spell.get())))
 				mySpells.push_back(spell.get());
 			continue;
 		}
@@ -359,6 +367,9 @@ void CSpellWindow::fexitb()
 	(myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastTabBattle : myInt->localState->spellbookSettings.spellbookLastTabAdvmap) = selectedTab;
 	(myInt->battleInt ? myInt->localState->spellbookSettings.spellbookLastPageBattle : myInt->localState->spellbookSettings.spellbookLastPageAdvmap) = currentPage;
 
+	if(onSpellSelect)
+		onSpellSelect(SpellID::NONE);
+
 	close();
 }
 
@@ -605,7 +616,7 @@ void CSpellWindow::SpellArea::clickPressed(const Point & cursorPosition)
 		if(owner->onSpellSelect)
 		{
 			owner->onSpellSelect(mySpell->id);
-			owner->fexitb();
+			owner->close();
 			return;
 		}
 

+ 4 - 0
client/windows/CSpellWindow.h

@@ -27,6 +27,7 @@ class CPlayerInterface;
 class CSpellWindow;
 class CTextInput;
 class TransparentFilledRectangle;
+class CToggleButton;
 
 /// The spell window
 class CSpellWindow : public CWindowObject
@@ -82,6 +83,9 @@ class CSpellWindow : public CWindowObject
 	std::shared_ptr<TransparentFilledRectangle> searchBoxRectangle;
 	std::shared_ptr<CLabel> searchBoxDescription;
 
+	std::shared_ptr<CToggleButton> showAllSpells;
+	std::shared_ptr<CLabel> showAllSpellsDescription;
+
 	bool isBigSpellbook;
 	int spellsPerPage;
 	int offL;