mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-02 00:10:22 +02:00
Merge pull request #4020 from Laserlicht/quickspell
[1.6] Quickspell support
This commit is contained in:
commit
31caf73383
@ -31,6 +31,7 @@
|
|||||||
#include "../render/IFont.h"
|
#include "../render/IFont.h"
|
||||||
#include "../render/Graphics.h"
|
#include "../render/Graphics.h"
|
||||||
#include "../widgets/Buttons.h"
|
#include "../widgets/Buttons.h"
|
||||||
|
#include "../widgets/CComponent.h"
|
||||||
#include "../widgets/Images.h"
|
#include "../widgets/Images.h"
|
||||||
#include "../widgets/Slider.h"
|
#include "../widgets/Slider.h"
|
||||||
#include "../widgets/TextControls.h"
|
#include "../widgets/TextControls.h"
|
||||||
@ -39,9 +40,11 @@
|
|||||||
#include "../windows/CMessage.h"
|
#include "../windows/CMessage.h"
|
||||||
#include "../windows/CCreatureWindow.h"
|
#include "../windows/CCreatureWindow.h"
|
||||||
#include "../windows/CSpellWindow.h"
|
#include "../windows/CSpellWindow.h"
|
||||||
|
#include "../windows/InfoWindows.h"
|
||||||
#include "../render/CAnimation.h"
|
#include "../render/CAnimation.h"
|
||||||
#include "../render/IRenderHandler.h"
|
#include "../render/IRenderHandler.h"
|
||||||
#include "../adventureMap/CInGameConsole.h"
|
#include "../adventureMap/CInGameConsole.h"
|
||||||
|
#include "../eventsSDL/InputHandler.h"
|
||||||
|
|
||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
#include "../../lib/CStack.h"
|
#include "../../lib/CStack.h"
|
||||||
@ -55,6 +58,8 @@
|
|||||||
#include "../../lib/mapObjects/CGTownInstance.h"
|
#include "../../lib/mapObjects/CGTownInstance.h"
|
||||||
#include "../../lib/networkPacks/PacksForClientBattle.h"
|
#include "../../lib/networkPacks/PacksForClientBattle.h"
|
||||||
#include "../../lib/TextOperations.h"
|
#include "../../lib/TextOperations.h"
|
||||||
|
#include "../../lib/json/JsonUtils.h"
|
||||||
|
|
||||||
|
|
||||||
void BattleConsole::showAll(Canvas & to)
|
void BattleConsole::showAll(Canvas & to)
|
||||||
{
|
{
|
||||||
@ -417,6 +422,79 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
|
|||||||
addUsedEvents(TIME);
|
addUsedEvents(TIME);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QuickSpellPanel::QuickSpellPanel(BattleInterface & owner)
|
||||||
|
: CIntObject(0), owner(owner)
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||||
|
|
||||||
|
addUsedEvents(LCLICK | SHOW_POPUP | MOVE);
|
||||||
|
|
||||||
|
pos = Rect(0, 0, 52, 600);
|
||||||
|
background = std::make_shared<CFilledTexture>(ImagePath::builtin("DIBOXBCK"), pos);
|
||||||
|
rect = std::make_shared<TransparentFilledRectangle>(Rect(0, 0, pos.w + 1, pos.h + 1), ColorRGBA(0, 0, 0, 0), ColorRGBA(241, 216, 120, 255));
|
||||||
|
|
||||||
|
create();
|
||||||
|
}
|
||||||
|
|
||||||
|
void QuickSpellPanel::create()
|
||||||
|
{
|
||||||
|
OBJECT_CONSTRUCTION_CAPTURING(255-DISPOSE);
|
||||||
|
|
||||||
|
const JsonNode config = JsonUtils::assembleFromFiles("config/shortcutsConfig");
|
||||||
|
|
||||||
|
labels.clear();
|
||||||
|
buttons.clear();
|
||||||
|
buttonsDisabled.clear();
|
||||||
|
|
||||||
|
auto hero = owner.getBattle()->battleGetMyHero();
|
||||||
|
if(!hero)
|
||||||
|
return;
|
||||||
|
|
||||||
|
for(int i = 0; i < 12; 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
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))
|
||||||
|
{
|
||||||
|
owner.castThisSpell(id);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
button->setOverlay(std::make_shared<CAnimImage>(AnimationPath::builtin("spellint"), !spellIdentifier.empty() ? 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;
|
||||||
|
create();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
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)));
|
||||||
|
}
|
||||||
|
labels.push_back(std::make_shared<CLabel>(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);
|
||||||
|
}
|
||||||
|
|
||||||
HeroInfoBasicPanel::HeroInfoBasicPanel(const InfoAboutHero & hero, Point * position, bool initializeBackground)
|
HeroInfoBasicPanel::HeroInfoBasicPanel(const InfoAboutHero & hero, Point * position, bool initializeBackground)
|
||||||
: CIntObject(0)
|
: CIntObject(0)
|
||||||
{
|
{
|
||||||
|
@ -22,6 +22,7 @@ class CGHeroInstance;
|
|||||||
struct BattleResult;
|
struct BattleResult;
|
||||||
struct InfoAboutHero;
|
struct InfoAboutHero;
|
||||||
class CStack;
|
class CStack;
|
||||||
|
class CPlayerBattleCallback;
|
||||||
|
|
||||||
namespace battle
|
namespace battle
|
||||||
{
|
{
|
||||||
@ -44,6 +45,7 @@ class TransparentFilledRectangle;
|
|||||||
class CPlayerInterface;
|
class CPlayerInterface;
|
||||||
class BattleRenderer;
|
class BattleRenderer;
|
||||||
class VideoWidget;
|
class VideoWidget;
|
||||||
|
class QuickSpellPanel;
|
||||||
|
|
||||||
/// Class which shows the console at the bottom of the battle screen and manages the text of the console
|
/// Class which shows the console at the bottom of the battle screen and manages the text of the console
|
||||||
class BattleConsole : public CIntObject, public IStatusBar
|
class BattleConsole : public CIntObject, public IStatusBar
|
||||||
@ -147,6 +149,26 @@ public:
|
|||||||
BattleHero(const BattleInterface & owner, const CGHeroInstance * hero, bool defender);
|
BattleHero(const BattleInterface & owner, const CGHeroInstance * hero, bool defender);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
class QuickSpellPanel : public CIntObject
|
||||||
|
{
|
||||||
|
private:
|
||||||
|
std::shared_ptr<CFilledTexture> background;
|
||||||
|
std::shared_ptr<TransparentFilledRectangle> rect;
|
||||||
|
std::vector<std::shared_ptr<CButton>> buttons;
|
||||||
|
std::vector<std::shared_ptr<TransparentFilledRectangle>> buttonsDisabled;
|
||||||
|
std::vector<std::shared_ptr<CLabel>> labels;
|
||||||
|
|
||||||
|
BattleInterface & owner;
|
||||||
|
public:
|
||||||
|
bool isEnabled; // isActive() is not working on multiple conditions, because of this we need a seperate flag
|
||||||
|
|
||||||
|
QuickSpellPanel(BattleInterface & owner);
|
||||||
|
|
||||||
|
void create();
|
||||||
|
|
||||||
|
void show(Canvas & to) override;
|
||||||
|
};
|
||||||
|
|
||||||
class HeroInfoBasicPanel : public CIntObject //extracted from InfoWindow to fit better as non-popup embed element
|
class HeroInfoBasicPanel : public CIntObject //extracted from InfoWindow to fit better as non-popup embed element
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
|
@ -45,8 +45,8 @@
|
|||||||
#include "../../lib/CPlayerState.h"
|
#include "../../lib/CPlayerState.h"
|
||||||
#include "../windows/settings/SettingsMainWindow.h"
|
#include "../windows/settings/SettingsMainWindow.h"
|
||||||
|
|
||||||
BattleWindow::BattleWindow(BattleInterface & owner):
|
BattleWindow::BattleWindow(BattleInterface & Owner):
|
||||||
owner(owner),
|
owner(Owner),
|
||||||
lastAlternativeAction(PossiblePlayerBattleAction::INVALID)
|
lastAlternativeAction(PossiblePlayerBattleAction::INVALID)
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||||
@ -64,6 +64,20 @@ BattleWindow::BattleWindow(BattleInterface & owner):
|
|||||||
|
|
||||||
const JsonNode config(JsonPath::builtin("config/widgets/BattleWindow2.json"));
|
const JsonNode config(JsonPath::builtin("config/widgets/BattleWindow2.json"));
|
||||||
|
|
||||||
|
addShortcut(EShortcut::BATTLE_TOGGLE_QUICKSPELL, [this](){ this->toggleStickyQuickSpellVisibility();});
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_0, [this](){ useSpellIfPossible(0); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_1, [this](){ useSpellIfPossible(1); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_2, [this](){ useSpellIfPossible(2); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_3, [this](){ useSpellIfPossible(3); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_4, [this](){ useSpellIfPossible(4); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_5, [this](){ useSpellIfPossible(5); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_6, [this](){ useSpellIfPossible(6); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_7, [this](){ useSpellIfPossible(7); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_8, [this](){ useSpellIfPossible(8); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_9, [this](){ useSpellIfPossible(9); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_10, [this](){ useSpellIfPossible(10); });
|
||||||
|
addShortcut(EShortcut::BATTLE_SPELL_SHORTCUT_11, [this](){ useSpellIfPossible(11); });
|
||||||
|
|
||||||
addShortcut(EShortcut::GLOBAL_OPTIONS, std::bind(&BattleWindow::bOptionsf, this));
|
addShortcut(EShortcut::GLOBAL_OPTIONS, std::bind(&BattleWindow::bOptionsf, this));
|
||||||
addShortcut(EShortcut::BATTLE_SURRENDER, std::bind(&BattleWindow::bSurrenderf, this));
|
addShortcut(EShortcut::BATTLE_SURRENDER, std::bind(&BattleWindow::bSurrenderf, this));
|
||||||
addShortcut(EShortcut::BATTLE_RETREAT, std::bind(&BattleWindow::bFleef, this));
|
addShortcut(EShortcut::BATTLE_RETREAT, std::bind(&BattleWindow::bFleef, this));
|
||||||
@ -95,6 +109,7 @@ BattleWindow::BattleWindow(BattleInterface & owner):
|
|||||||
owner.fieldController->createHeroes();
|
owner.fieldController->createHeroes();
|
||||||
|
|
||||||
createQueue();
|
createQueue();
|
||||||
|
createQuickSpellWindow();
|
||||||
createStickyHeroInfoWindows();
|
createStickyHeroInfoWindows();
|
||||||
createTimerInfoWindows();
|
createTimerInfoWindows();
|
||||||
|
|
||||||
@ -164,10 +179,67 @@ void BattleWindow::createStickyHeroInfoWindows()
|
|||||||
setPositionInfoWindow();
|
setPositionInfoWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleWindow::createQuickSpellWindow()
|
||||||
|
{
|
||||||
|
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||||
|
|
||||||
|
quickSpellWindow = std::make_shared<QuickSpellPanel>(owner);
|
||||||
|
quickSpellWindow->moveTo(Point(pos.x - 67, pos.y));
|
||||||
|
|
||||||
|
if(settings["battle"]["enableQuickSpellPanel"].Bool())
|
||||||
|
showStickyQuickSpellWindow();
|
||||||
|
else
|
||||||
|
hideStickyQuickSpellWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleWindow::toggleStickyQuickSpellVisibility()
|
||||||
|
{
|
||||||
|
if(settings["battle"]["enableQuickSpellPanel"].Bool())
|
||||||
|
hideStickyQuickSpellWindow();
|
||||||
|
else
|
||||||
|
showStickyQuickSpellWindow();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleWindow::hideStickyQuickSpellWindow()
|
||||||
|
{
|
||||||
|
Settings showStickyQuickSpellWindow = settings.write["battle"]["enableQuickSpellPanel"];
|
||||||
|
showStickyQuickSpellWindow->Bool() = false;
|
||||||
|
|
||||||
|
quickSpellWindow->disable();
|
||||||
|
quickSpellWindow->isEnabled = false;
|
||||||
|
|
||||||
|
setPositionInfoWindow();
|
||||||
|
createTimerInfoWindows();
|
||||||
|
GH.windows().totalRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleWindow::showStickyQuickSpellWindow()
|
||||||
|
{
|
||||||
|
Settings showStickyQuickSpellWindow = settings.write["battle"]["enableQuickSpellPanel"];
|
||||||
|
showStickyQuickSpellWindow->Bool() = true;
|
||||||
|
|
||||||
|
if(GH.screenDimensions().x >= 1050)
|
||||||
|
{
|
||||||
|
quickSpellWindow->enable();
|
||||||
|
quickSpellWindow->isEnabled = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
quickSpellWindow->disable();
|
||||||
|
quickSpellWindow->isEnabled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
setPositionInfoWindow();
|
||||||
|
createTimerInfoWindows();
|
||||||
|
GH.windows().totalRedraw();
|
||||||
|
}
|
||||||
|
|
||||||
void BattleWindow::createTimerInfoWindows()
|
void BattleWindow::createTimerInfoWindows()
|
||||||
{
|
{
|
||||||
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE;
|
||||||
|
|
||||||
|
int xOffsetAttacker = quickSpellWindow->isEnabled ? -53 : 0;
|
||||||
|
|
||||||
if(LOCPLINT->cb->getStartInfo()->turnTimerInfo.battleTimer != 0 || LOCPLINT->cb->getStartInfo()->turnTimerInfo.unitTimer != 0)
|
if(LOCPLINT->cb->getStartInfo()->turnTimerInfo.battleTimer != 0 || LOCPLINT->cb->getStartInfo()->turnTimerInfo.unitTimer != 0)
|
||||||
{
|
{
|
||||||
PlayerColor attacker = owner.getBattle()->sideToPlayer(BattleSide::ATTACKER);
|
PlayerColor attacker = owner.getBattle()->sideToPlayer(BattleSide::ATTACKER);
|
||||||
@ -176,7 +248,7 @@ void BattleWindow::createTimerInfoWindows()
|
|||||||
if (attacker.isValidPlayer())
|
if (attacker.isValidPlayer())
|
||||||
{
|
{
|
||||||
if (GH.screenDimensions().x >= 1000)
|
if (GH.screenDimensions().x >= 1000)
|
||||||
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(-92, 1), attacker);
|
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(-92 + xOffsetAttacker, 1), attacker);
|
||||||
else
|
else
|
||||||
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(1, 135), attacker);
|
attackerTimerWidget = std::make_shared<TurnTimerWidget>(Point(1, 135), attacker);
|
||||||
}
|
}
|
||||||
@ -199,6 +271,24 @@ std::shared_ptr<BattleConsole> BattleWindow::buildBattleConsole(const JsonNode &
|
|||||||
return std::make_shared<BattleConsole>(owner, background, rect.topLeft(), offset, rect.dimensions() );
|
return std::make_shared<BattleConsole>(owner, background, rect.topLeft(), offset, rect.dimensions() );
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if(id.hasValue() && owner.getBattle()->battleGetMyHero() && id.toSpell()->canBeCast(owner.getBattle().get(), spells::Mode::HERO, owner.getBattle()->battleGetMyHero()))
|
||||||
|
{
|
||||||
|
owner.castThisSpell(id);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
void BattleWindow::toggleQueueVisibility()
|
void BattleWindow::toggleQueueVisibility()
|
||||||
{
|
{
|
||||||
if(settings["battle"]["showQueue"].Bool())
|
if(settings["battle"]["showQueue"].Bool())
|
||||||
@ -283,10 +373,12 @@ void BattleWindow::showStickyHeroWindows()
|
|||||||
void BattleWindow::updateQueue()
|
void BattleWindow::updateQueue()
|
||||||
{
|
{
|
||||||
queue->update();
|
queue->update();
|
||||||
|
createQuickSpellWindow();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleWindow::setPositionInfoWindow()
|
void BattleWindow::setPositionInfoWindow()
|
||||||
{
|
{
|
||||||
|
int xOffsetAttacker = quickSpellWindow->isEnabled ? -53 : 0;
|
||||||
if(defenderHeroWindow)
|
if(defenderHeroWindow)
|
||||||
{
|
{
|
||||||
Point position = (GH.screenDimensions().x >= 1000)
|
Point position = (GH.screenDimensions().x >= 1000)
|
||||||
@ -297,7 +389,7 @@ void BattleWindow::setPositionInfoWindow()
|
|||||||
if(attackerHeroWindow)
|
if(attackerHeroWindow)
|
||||||
{
|
{
|
||||||
Point position = (GH.screenDimensions().x >= 1000)
|
Point position = (GH.screenDimensions().x >= 1000)
|
||||||
? Point(pos.x - 93, pos.y + 60)
|
? Point(pos.x - 93 + xOffsetAttacker, pos.y + 60)
|
||||||
: Point(pos.x + 1, pos.y + 195);
|
: Point(pos.x + 1, pos.y + 195);
|
||||||
attackerHeroWindow->moveTo(position);
|
attackerHeroWindow->moveTo(position);
|
||||||
}
|
}
|
||||||
@ -311,7 +403,7 @@ void BattleWindow::setPositionInfoWindow()
|
|||||||
if(attackerStackWindow)
|
if(attackerStackWindow)
|
||||||
{
|
{
|
||||||
Point position = (GH.screenDimensions().x >= 1000)
|
Point position = (GH.screenDimensions().x >= 1000)
|
||||||
? Point(pos.x - 93, attackerHeroWindow ? attackerHeroWindow->pos.y + 210 : pos.y + 60)
|
? Point(pos.x - 93 + xOffsetAttacker, attackerHeroWindow ? attackerHeroWindow->pos.y + 210 : pos.y + 60)
|
||||||
: Point(pos.x + 1, attackerHeroWindow ? attackerHeroWindow->pos.y : pos.y + 195);
|
: Point(pos.x + 1, attackerHeroWindow ? attackerHeroWindow->pos.y : pos.y + 195);
|
||||||
attackerStackWindow->moveTo(position);
|
attackerStackWindow->moveTo(position);
|
||||||
}
|
}
|
||||||
@ -346,6 +438,7 @@ void BattleWindow::updateStackInfoWindow(const CStack * stack)
|
|||||||
attackerStackWindow = nullptr;
|
attackerStackWindow = nullptr;
|
||||||
|
|
||||||
setPositionInfoWindow();
|
setPositionInfoWindow();
|
||||||
|
createTimerInfoWindows();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleWindow::heroManaPointsChanged(const CGHeroInstance * hero)
|
void BattleWindow::heroManaPointsChanged(const CGHeroInstance * hero)
|
||||||
@ -765,6 +858,8 @@ void BattleWindow::blockUI(bool on)
|
|||||||
setShortcutBlocked(EShortcut::BATTLE_TACTICS_NEXT, on || !owner.tacticsMode);
|
setShortcutBlocked(EShortcut::BATTLE_TACTICS_NEXT, on || !owner.tacticsMode);
|
||||||
setShortcutBlocked(EShortcut::BATTLE_CONSOLE_DOWN, on && !owner.tacticsMode);
|
setShortcutBlocked(EShortcut::BATTLE_CONSOLE_DOWN, on && !owner.tacticsMode);
|
||||||
setShortcutBlocked(EShortcut::BATTLE_CONSOLE_UP, on && !owner.tacticsMode);
|
setShortcutBlocked(EShortcut::BATTLE_CONSOLE_UP, on && !owner.tacticsMode);
|
||||||
|
|
||||||
|
quickSpellWindow->setInputEnabled(!on);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleWindow::bOpenActiveUnit()
|
void BattleWindow::bOpenActiveUnit()
|
||||||
|
@ -27,6 +27,7 @@ class StackQueue;
|
|||||||
class TurnTimerWidget;
|
class TurnTimerWidget;
|
||||||
class HeroInfoBasicPanel;
|
class HeroInfoBasicPanel;
|
||||||
class StackInfoBasicPanel;
|
class StackInfoBasicPanel;
|
||||||
|
class QuickSpellPanel;
|
||||||
|
|
||||||
/// GUI object that handles functionality of panel at the bottom of combat screen
|
/// GUI object that handles functionality of panel at the bottom of combat screen
|
||||||
class BattleWindow : public InterfaceObjectConfigurable
|
class BattleWindow : public InterfaceObjectConfigurable
|
||||||
@ -40,6 +41,8 @@ class BattleWindow : public InterfaceObjectConfigurable
|
|||||||
std::shared_ptr<StackInfoBasicPanel> attackerStackWindow;
|
std::shared_ptr<StackInfoBasicPanel> attackerStackWindow;
|
||||||
std::shared_ptr<StackInfoBasicPanel> defenderStackWindow;
|
std::shared_ptr<StackInfoBasicPanel> defenderStackWindow;
|
||||||
|
|
||||||
|
std::shared_ptr<QuickSpellPanel> quickSpellWindow;
|
||||||
|
|
||||||
std::shared_ptr<TurnTimerWidget> attackerTimerWidget;
|
std::shared_ptr<TurnTimerWidget> attackerTimerWidget;
|
||||||
std::shared_ptr<TurnTimerWidget> defenderTimerWidget;
|
std::shared_ptr<TurnTimerWidget> defenderTimerWidget;
|
||||||
|
|
||||||
@ -68,12 +71,16 @@ class BattleWindow : public InterfaceObjectConfigurable
|
|||||||
PossiblePlayerBattleAction lastAlternativeAction;
|
PossiblePlayerBattleAction lastAlternativeAction;
|
||||||
void showAlternativeActionIcon(PossiblePlayerBattleAction);
|
void showAlternativeActionIcon(PossiblePlayerBattleAction);
|
||||||
|
|
||||||
|
void useSpellIfPossible(int slot);
|
||||||
|
|
||||||
/// flip battle queue visibility to opposite
|
/// flip battle queue visibility to opposite
|
||||||
void toggleQueueVisibility();
|
void toggleQueueVisibility();
|
||||||
void createQueue();
|
void createQueue();
|
||||||
|
|
||||||
void toggleStickyHeroWindowsVisibility();
|
void toggleStickyHeroWindowsVisibility();
|
||||||
|
void toggleStickyQuickSpellVisibility();
|
||||||
void createStickyHeroInfoWindows();
|
void createStickyHeroInfoWindows();
|
||||||
|
void createQuickSpellWindow();
|
||||||
void createTimerInfoWindows();
|
void createTimerInfoWindows();
|
||||||
|
|
||||||
std::shared_ptr<BattleConsole> buildBattleConsole(const JsonNode &) const;
|
std::shared_ptr<BattleConsole> buildBattleConsole(const JsonNode &) const;
|
||||||
@ -94,6 +101,10 @@ public:
|
|||||||
void hideStickyHeroWindows();
|
void hideStickyHeroWindows();
|
||||||
void showStickyHeroWindows();
|
void showStickyHeroWindows();
|
||||||
|
|
||||||
|
/// Toggle permanent quickspell windows visibility
|
||||||
|
void hideStickyQuickSpellWindow();
|
||||||
|
void showStickyQuickSpellWindow();
|
||||||
|
|
||||||
/// Event handler for netpack changing hero mana points
|
/// Event handler for netpack changing hero mana points
|
||||||
void heroManaPointsChanged(const CGHeroInstance * hero);
|
void heroManaPointsChanged(const CGHeroInstance * hero);
|
||||||
|
|
||||||
|
@ -186,6 +186,19 @@ enum class EShortcut
|
|||||||
BATTLE_TOGGLE_HEROES_STATS,
|
BATTLE_TOGGLE_HEROES_STATS,
|
||||||
BATTLE_OPEN_ACTIVE_UNIT,
|
BATTLE_OPEN_ACTIVE_UNIT,
|
||||||
BATTLE_OPEN_HOVERED_UNIT,
|
BATTLE_OPEN_HOVERED_UNIT,
|
||||||
|
BATTLE_TOGGLE_QUICKSPELL,
|
||||||
|
BATTLE_SPELL_SHORTCUT_0,
|
||||||
|
BATTLE_SPELL_SHORTCUT_1,
|
||||||
|
BATTLE_SPELL_SHORTCUT_2,
|
||||||
|
BATTLE_SPELL_SHORTCUT_3,
|
||||||
|
BATTLE_SPELL_SHORTCUT_4,
|
||||||
|
BATTLE_SPELL_SHORTCUT_5,
|
||||||
|
BATTLE_SPELL_SHORTCUT_6,
|
||||||
|
BATTLE_SPELL_SHORTCUT_7,
|
||||||
|
BATTLE_SPELL_SHORTCUT_8,
|
||||||
|
BATTLE_SPELL_SHORTCUT_9,
|
||||||
|
BATTLE_SPELL_SHORTCUT_10,
|
||||||
|
BATTLE_SPELL_SHORTCUT_11,
|
||||||
|
|
||||||
MARKET_DEAL,
|
MARKET_DEAL,
|
||||||
MARKET_MAX_AMOUNT,
|
MARKET_MAX_AMOUNT,
|
||||||
|
@ -222,6 +222,19 @@ EShortcut ShortcutHandler::findShortcut(const std::string & identifier ) const
|
|||||||
{"battleTacticsNext", EShortcut::BATTLE_TACTICS_NEXT },
|
{"battleTacticsNext", EShortcut::BATTLE_TACTICS_NEXT },
|
||||||
{"battleTacticsEnd", EShortcut::BATTLE_TACTICS_END },
|
{"battleTacticsEnd", EShortcut::BATTLE_TACTICS_END },
|
||||||
{"battleSelectAction", EShortcut::BATTLE_SELECT_ACTION },
|
{"battleSelectAction", EShortcut::BATTLE_SELECT_ACTION },
|
||||||
|
{"battleToggleQuickSpell", EShortcut::BATTLE_TOGGLE_QUICKSPELL },
|
||||||
|
{"battleSpellShortcut0", EShortcut::BATTLE_SPELL_SHORTCUT_0 },
|
||||||
|
{"battleSpellShortcut1", EShortcut::BATTLE_SPELL_SHORTCUT_1 },
|
||||||
|
{"battleSpellShortcut2", EShortcut::BATTLE_SPELL_SHORTCUT_2 },
|
||||||
|
{"battleSpellShortcut3", EShortcut::BATTLE_SPELL_SHORTCUT_3 },
|
||||||
|
{"battleSpellShortcut4", EShortcut::BATTLE_SPELL_SHORTCUT_4 },
|
||||||
|
{"battleSpellShortcut5", EShortcut::BATTLE_SPELL_SHORTCUT_5 },
|
||||||
|
{"battleSpellShortcut6", EShortcut::BATTLE_SPELL_SHORTCUT_6 },
|
||||||
|
{"battleSpellShortcut7", EShortcut::BATTLE_SPELL_SHORTCUT_7 },
|
||||||
|
{"battleSpellShortcut8", EShortcut::BATTLE_SPELL_SHORTCUT_8 },
|
||||||
|
{"battleSpellShortcut9", EShortcut::BATTLE_SPELL_SHORTCUT_9 },
|
||||||
|
{"battleSpellShortcut10", EShortcut::BATTLE_SPELL_SHORTCUT_10 },
|
||||||
|
{"battleSpellShortcut11", EShortcut::BATTLE_SPELL_SHORTCUT_11 },
|
||||||
{"spectateTrackHero", EShortcut::SPECTATE_TRACK_HERO },
|
{"spectateTrackHero", EShortcut::SPECTATE_TRACK_HERO },
|
||||||
{"spectateSkipBattle", EShortcut::SPECTATE_SKIP_BATTLE },
|
{"spectateSkipBattle", EShortcut::SPECTATE_SKIP_BATTLE },
|
||||||
{"spectateSkipBattleResult", EShortcut::SPECTATE_SKIP_BATTLE_RESULT },
|
{"spectateSkipBattleResult", EShortcut::SPECTATE_SKIP_BATTLE_RESULT },
|
||||||
|
@ -67,6 +67,11 @@ void CButton::addCallback(const std::function<void()> & callback)
|
|||||||
this->callback += callback;
|
this->callback += callback;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CButton::addPopupCallback(const std::function<void()> & callback)
|
||||||
|
{
|
||||||
|
this->callbackPopup += callback;
|
||||||
|
}
|
||||||
|
|
||||||
void ButtonBase::setTextOverlay(const std::string & Text, EFonts font, ColorRGBA color)
|
void ButtonBase::setTextOverlay(const std::string & Text, EFonts font, ColorRGBA color)
|
||||||
{
|
{
|
||||||
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING(255-DISPOSE);
|
||||||
@ -289,6 +294,8 @@ void CButton::clickCancel(const Point & cursorPosition)
|
|||||||
|
|
||||||
void CButton::showPopupWindow(const Point & cursorPosition)
|
void CButton::showPopupWindow(const Point & cursorPosition)
|
||||||
{
|
{
|
||||||
|
callbackPopup();
|
||||||
|
|
||||||
if(!helpBox.empty()) //there is no point to show window with nothing inside...
|
if(!helpBox.empty()) //there is no point to show window with nothing inside...
|
||||||
CRClickPopup::createAndPush(helpBox);
|
CRClickPopup::createAndPush(helpBox);
|
||||||
}
|
}
|
||||||
|
@ -69,6 +69,7 @@ public:
|
|||||||
class CButton : public ButtonBase
|
class CButton : public ButtonBase
|
||||||
{
|
{
|
||||||
CFunctionList<void()> callback;
|
CFunctionList<void()> callback;
|
||||||
|
CFunctionList<void()> callbackPopup;
|
||||||
|
|
||||||
std::array<std::string, 4> hoverTexts; //texts for statusbar, if empty - first entry will be used
|
std::array<std::string, 4> hoverTexts; //texts for statusbar, if empty - first entry will be used
|
||||||
std::optional<ColorRGBA> borderColor; // mapping of button state to border color
|
std::optional<ColorRGBA> borderColor; // mapping of button state to border color
|
||||||
@ -90,6 +91,7 @@ public:
|
|||||||
|
|
||||||
/// adds one more callback to on-click actions
|
/// adds one more callback to on-click actions
|
||||||
void addCallback(const std::function<void()> & callback);
|
void addCallback(const std::function<void()> & callback);
|
||||||
|
void addPopupCallback(const std::function<void()> & callback);
|
||||||
|
|
||||||
void addHoverText(EButtonState state, const std::string & text);
|
void addHoverText(EButtonState state, const std::string & text);
|
||||||
|
|
||||||
|
@ -98,13 +98,15 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells):
|
CSpellWindow::CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells, std::function<void(SpellID)> onSpellSelect):
|
||||||
CWindowObject(PLAYER_COLORED | (settings["gameTweaks"]["enableLargeSpellbook"].Bool() ? BORDERED : 0)),
|
CWindowObject(PLAYER_COLORED | (settings["gameTweaks"]["enableLargeSpellbook"].Bool() ? BORDERED : 0)),
|
||||||
battleSpellsOnly(openOnBattleSpells),
|
battleSpellsOnly(openOnBattleSpells),
|
||||||
selectedTab(4),
|
selectedTab(4),
|
||||||
currentPage(0),
|
currentPage(0),
|
||||||
myHero(_myHero),
|
myHero(_myHero),
|
||||||
myInt(_myInt),
|
myInt(_myInt),
|
||||||
|
openOnBattleSpells(openOnBattleSpells),
|
||||||
|
onSpellSelect(onSpellSelect),
|
||||||
isBigSpellbook(settings["gameTweaks"]["enableLargeSpellbook"].Bool()),
|
isBigSpellbook(settings["gameTweaks"]["enableLargeSpellbook"].Bool()),
|
||||||
spellsPerPage(24),
|
spellsPerPage(24),
|
||||||
offL(-11),
|
offL(-11),
|
||||||
@ -293,6 +295,14 @@ void CSpellWindow::processSpells()
|
|||||||
for(auto const & spell : CGI->spellh->objects)
|
for(auto const & spell : CGI->spellh->objects)
|
||||||
{
|
{
|
||||||
bool searchTextFound = !searchBox || boost::algorithm::contains(boost::algorithm::to_lower_copy(spell->getNameTranslated()), boost::algorithm::to_lower_copy(searchBox->getText()));
|
bool searchTextFound = !searchBox || boost::algorithm::contains(boost::algorithm::to_lower_copy(spell->getNameTranslated()), boost::algorithm::to_lower_copy(searchBox->getText()));
|
||||||
|
|
||||||
|
if(onSpellSelect)
|
||||||
|
{
|
||||||
|
if(spell->isCombat() == openOnBattleSpells && !spell->isSpecial() && !spell->isCreatureAbility())
|
||||||
|
mySpells.push_back(spell.get());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell.get()) && searchTextFound)
|
if(!spell->isCreatureAbility() && myHero->canCastThisSpell(spell.get()) && searchTextFound)
|
||||||
mySpells.push_back(spell.get());
|
mySpells.push_back(spell.get());
|
||||||
}
|
}
|
||||||
@ -602,6 +612,13 @@ void CSpellWindow::SpellArea::clickPressed(const Point & cursorPosition)
|
|||||||
{
|
{
|
||||||
if(mySpell)
|
if(mySpell)
|
||||||
{
|
{
|
||||||
|
if(owner->onSpellSelect)
|
||||||
|
{
|
||||||
|
owner->onSpellSelect(mySpell->id);
|
||||||
|
owner->fexitb();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
auto spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero);
|
auto spellCost = owner->myInt->cb->getSpellCost(mySpell, owner->myHero);
|
||||||
if(spellCost > owner->myHero->mana) //insufficient mana
|
if(spellCost > owner->myHero->mana) //insufficient mana
|
||||||
{
|
{
|
||||||
@ -738,7 +755,7 @@ void CSpellWindow::SpellArea::setSpell(const CSpell * spell)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ColorRGBA firstLineColor, secondLineColor;
|
ColorRGBA firstLineColor, secondLineColor;
|
||||||
if(spellCost > owner->myHero->mana) //hero cannot cast this spell
|
if(spellCost > owner->myHero->mana && !owner->onSpellSelect) //hero cannot cast this spell
|
||||||
{
|
{
|
||||||
firstLineColor = Colors::WHITE;
|
firstLineColor = Colors::WHITE;
|
||||||
secondLineColor = Colors::ORANGE;
|
secondLineColor = Colors::ORANGE;
|
||||||
|
@ -115,8 +115,11 @@ class CSpellWindow : public CWindowObject
|
|||||||
|
|
||||||
std::shared_ptr<IImage> createBigSpellBook();
|
std::shared_ptr<IImage> createBigSpellBook();
|
||||||
|
|
||||||
|
bool openOnBattleSpells;
|
||||||
|
std::function<void(SpellID)> onSpellSelect; //external processing of selected spell
|
||||||
|
|
||||||
public:
|
public:
|
||||||
CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells = true);
|
CSpellWindow(const CGHeroInstance * _myHero, CPlayerInterface * _myInt, bool openOnBattleSpells = true, std::function<void(SpellID)> onSpellSelect = nullptr);
|
||||||
~CSpellWindow();
|
~CSpellWindow();
|
||||||
|
|
||||||
void fexitb();
|
void fexitb();
|
||||||
|
@ -372,7 +372,7 @@
|
|||||||
"type" : "object",
|
"type" : "object",
|
||||||
"additionalProperties" : false,
|
"additionalProperties" : false,
|
||||||
"default" : {},
|
"default" : {},
|
||||||
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "rangeLimitHighlightOnHover", "showQueue", "swipeAttackDistance", "queueSize", "stickyHeroInfoWindows", "enableAutocombatSpells", "endWithAutocombat", "queueSmallSlots", "queueSmallOutside" ],
|
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "rangeLimitHighlightOnHover", "showQueue", "swipeAttackDistance", "queueSize", "stickyHeroInfoWindows", "enableAutocombatSpells", "endWithAutocombat", "queueSmallSlots", "queueSmallOutside", "enableQuickSpellPanel" ],
|
||||||
"properties" : {
|
"properties" : {
|
||||||
"speedFactor" : {
|
"speedFactor" : {
|
||||||
"type" : "number",
|
"type" : "number",
|
||||||
@ -430,6 +430,10 @@
|
|||||||
"queueSmallOutside" : {
|
"queueSmallOutside" : {
|
||||||
"type": "boolean",
|
"type": "boolean",
|
||||||
"default": false
|
"default": false
|
||||||
|
},
|
||||||
|
"enableQuickSpellPanel" : {
|
||||||
|
"type": "boolean",
|
||||||
|
"default": true
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -64,6 +64,19 @@
|
|||||||
"battleOpenHoveredUnit": "V",
|
"battleOpenHoveredUnit": "V",
|
||||||
"battleRetreat": "R",
|
"battleRetreat": "R",
|
||||||
"battleSelectAction": "S",
|
"battleSelectAction": "S",
|
||||||
|
"battleToggleQuickSpell": "T",
|
||||||
|
"battleSpellShortcut0": "1",
|
||||||
|
"battleSpellShortcut1": "2",
|
||||||
|
"battleSpellShortcut2": "3",
|
||||||
|
"battleSpellShortcut3": "4",
|
||||||
|
"battleSpellShortcut4": "5",
|
||||||
|
"battleSpellShortcut5": "6",
|
||||||
|
"battleSpellShortcut6": "7",
|
||||||
|
"battleSpellShortcut7": "8",
|
||||||
|
"battleSpellShortcut8": "9",
|
||||||
|
"battleSpellShortcut9": "0",
|
||||||
|
"battleSpellShortcut10": "N",
|
||||||
|
"battleSpellShortcut11": "M",
|
||||||
"battleSurrender": "S",
|
"battleSurrender": "S",
|
||||||
"battleTacticsEnd": [ "Return", "Keypad Enter"],
|
"battleTacticsEnd": [ "Return", "Keypad Enter"],
|
||||||
"battleTacticsNext": "Space",
|
"battleTacticsNext": "Space",
|
||||||
|
Loading…
Reference in New Issue
Block a user