/* * QuickSpellPanel.cpp, 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 * */ #include "StdInc.h" #include "QuickSpellPanel.h" #include "BattleInterface.h" #include "../GameEngine.h" #include "../eventsSDL/InputHandler.h" #include "../gui/WindowHandler.h" #include "../widgets/Buttons.h" #include "../widgets/GraphicalPrimitiveCanvas.h" #include "../widgets/Images.h" #include "../widgets/TextControls.h" #include "../windows/CSpellWindow.h" #include "../../lib/CConfigHandler.h" #include "../../lib/GameLibrary.h" #include "../../lib/battle/CPlayerBattleCallback.h" #include "../../lib/json/JsonUtils.h" #include "../../lib/mapObjects/CGHeroInstance.h" #include "../../lib/spells/CSpellHandler.h" QuickSpellPanel::QuickSpellPanel(BattleInterface & owner) : CIntObject(0) , owner(owner) { OBJECT_CONSTRUCTION; addUsedEvents(LCLICK | SHOW_POPUP | MOVE | INPUT_MODE_CHANGE); pos = Rect(0, 0, 52, 600); background = std::make_shared(ImagePath::builtin("DIBOXBCK"), pos); rect = std::make_shared(Rect(0, 0, pos.w + 1, pos.h + 1), ColorRGBA(0, 0, 0, 0), ColorRGBA(241, 216, 120, 255)); create(); } std::vector> QuickSpellPanel::getSpells() const { std::vector spellIds; std::vector 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 &) { id = SpellID::NONE; } spellIds.push_back(id); spellIdsFromSetting.push_back(id != SpellID::NONE); } // autofill empty slots with spells if possible const auto * hero = owner.getBattle()->battleGetMyHero(); for(int i = 0; i < QUICKSPELL_SLOTS; i++) { if(spellIds[i] != SpellID::NONE) continue; for(const auto & availableSpellID : LIBRARY->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> 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; const JsonNode config = JsonUtils::assembleFromFiles("config/shortcutsConfig"); labels.clear(); buttons.clear(); buttonsDisabled.clear(); const auto * hero = owner.getBattle()->battleGetMyHero(); if(!hero) return; auto spells = getSpells(); for(int i = 0; i < QUICKSPELL_SLOTS; i++) { SpellID id; bool fromSettings; std::tie(id, fromSettings) = spells[i]; auto button = std::make_shared(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)) { owner.castThisSpell(id); } }); button->setOverlay(std::make_shared(AnimationPath::builtin("spellint"), id != SpellID::NONE ? id.num + 1 : 0)); button->addPopupCallback([this, i, hero](){ ENGINE->input().hapticFeedback(); ENGINE->windows().createAndPushWindow(hero, owner.curInt.get(), true, [this, i](SpellID spell){ Settings configID = persistentStorage.write["quickSpell"][std::to_string(i)]; configID->String() = spell == SpellID::NONE ? "" : spell.toSpell()->identifier; create(); }); }); if(fromSettings) buttonsIsAutoGenerated.push_back(std::make_shared(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(Rect(2, 7 + 50 * i, 48, 36), ColorRGBA(0, 0, 0, 172))); } if(ENGINE->input().getCurrentInputMode() == InputMode::KEYBOARD_AND_MOUSE) labels.push_back(std::make_shared(7, 10 + 50 * i, EFonts::FONT_TINY, ETextAlignment::TOPLEFT, Colors::WHITE, config["keyboard"]["battleSpellShortcut" + std::to_string(i)].String())); buttons.push_back(button); } } void QuickSpellPanel::show(Canvas & to) { showAll(to); CIntObject::show(to); } void QuickSpellPanel::inputModeChanged(InputMode modi) { create(); redraw(); }