/* * BattleInterfaceClasses.h, 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 * */ #pragma once #include "BattleConstants.h" #include "../gui/CIntObject.h" #include "../../lib/FunctionList.h" #include "../../lib/battle/BattleHex.h" #include "../../lib/texts/MetaString.h" #include "../windows/CWindowObject.h" VCMI_LIB_NAMESPACE_BEGIN class CGHeroInstance; struct BattleResult; struct InfoAboutHero; class CStack; class CPlayerBattleCallback; namespace battle { class Unit; } VCMI_LIB_NAMESPACE_END class CAnimation; class Canvas; class BattleInterface; class CPicture; class CFilledTexture; class CButton; class CLabel; class CMultiLineLabel; class CTextBox; class CAnimImage; class TransparentFilledRectangle; class CPlayerInterface; class BattleRenderer; class VideoWidget; class QuickSpellPanel; /// 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 { private: const BattleInterface & owner; std::shared_ptr background; /// List of all texts added during battle, essentially - log of entire battle std::vector< std::string > logEntries; /// Current scrolling position, to allow showing older entries via scroll buttons int scrollPosition; /// current hover text set on mouse move, takes priority over log entries std::string hoverText; /// current text entered via in-game console, takes priority over both log entries and hover text std::string consoleText; /// if true then we are currently entering console text bool enteringText; /// splits text into individual strings for battle log std::vector splitText(const std::string &text); /// select line(s) that will be visible in UI std::vector getVisibleText() const; public: BattleConsole(const BattleInterface & owner, std::shared_ptr backgroundSource, const Point & objectPos, const Point & imagePos, const Point &size); void showAll(Canvas & to) override; void deactivate() override; void clickPressed(const Point & cursorPosition) override; bool addText(const std::string &text); //adds text at the last position; returns false if failed (e.g. text longer than 70 characters) void scrollUp(ui32 by = 1); //scrolls console up by 'by' positions void scrollDown(ui32 by = 1); //scrolls console up by 'by' positions // IStatusBar interface void write(const std::string & Text) override; void clearIfMatching(const std::string & Text) override; void clear() override; void setEnteringMode(bool on) override; void setEnteredText(const std::string & text) override; }; class BattleConsoleWindow : public CWindowObject { private: std::shared_ptr backgroundTexture; std::shared_ptr buttonOk; std::shared_ptr textBoxBackgroundBorder; std::shared_ptr textBox; public: BattleConsoleWindow(const std::string & text); }; /// Hero battle animation class BattleHero : public CIntObject { bool defender; CFunctionList phaseFinishedCallback; std::shared_ptr animation; std::shared_ptr flagAnimation; const CGHeroInstance * hero; //this animation's hero instance const BattleInterface & owner; //battle interface to which this animation is assigned EHeroAnimType phase; //stage of animation EHeroAnimType nextPhase; //stage of animation to be set after current phase is fully displayed float currentSpeed; float currentFrame; //frame of animation float flagCurrentFrame; void switchToNextPhase(); void render(Canvas & canvas); //prints next frame of animation to to public: const CGHeroInstance * instance(); void setPhase(EHeroAnimType newPhase); //sets phase of hero animation void collectRenderableObjects(BattleRenderer & renderer); void tick(uint32_t msPassed) override; float getFrame() const; void onPhaseFinished(const std::function &); void pause(); void play(); void heroLeftClicked(); void heroRightClicked(); BattleHero(const BattleInterface & owner, const CGHeroInstance * hero, bool defender); }; class QuickSpellPanel : public CIntObject { private: std::shared_ptr background; std::shared_ptr rect; std::vector> buttons; std::vector> buttonsIsAutoGenerated; std::vector> buttonsDisabled; std::vector> 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> getSpells() const; void show(Canvas & to) override; void inputModeChanged(InputMode modi) override; }; class HeroInfoBasicPanel : public CIntObject //extracted from InfoWindow to fit better as non-popup embed element { private: std::shared_ptr background; std::vector> labels; std::vector> icons; public: HeroInfoBasicPanel(const InfoAboutHero & hero, Point * position, bool initializeBackground = true); void show(Canvas & to) override; void initializeData(const InfoAboutHero & hero); void update(const InfoAboutHero & updatedInfo); }; class StackInfoBasicPanel : public CIntObject { private: std::shared_ptr background; std::shared_ptr background2; std::vector> labels; std::vector> labelsMultiline; std::vector> icons; public: StackInfoBasicPanel(const CStack * stack, bool initializeBackground = true); void show(Canvas & to) override; void initializeData(const CStack * stack); void update(const CStack * updatedInfo); }; class HeroInfoWindow : public CWindowObject { private: std::shared_ptr content; public: HeroInfoWindow(const InfoAboutHero & hero, Point * position); }; struct BattleResultResources { VideoPath prologueVideo; VideoPath loopedVideo; AudioPath musicName; MetaString resultText; }; /// Class which is responsible for showing the battle result window class BattleResultWindow : public WindowBase { private: std::shared_ptr background; std::vector> labels; std::shared_ptr exit; std::shared_ptr repeat; std::vector> icons; std::shared_ptr description; std::shared_ptr videoPlayer; CPlayerInterface & owner; BattleResultResources getResources(const BattleResult & br); void buttonPressed(int button); //internal function for button callbacks public: BattleResultWindow(const BattleResult & br, CPlayerInterface & _owner, bool allowReplay = false); void bExitf(); //exit button callback void bRepeatf(); //repeat button callback std::function resultCallback; //callback receiving which button was pressed void activate() override; }; /// Shows the stack queue class StackQueue : public CIntObject { class StackBox : public CIntObject { StackQueue * owner; std::optional boundUnitID; std::shared_ptr background; std::shared_ptr icon; std::shared_ptr amount; std::shared_ptr waitIcon; std::shared_ptr defendIcon; std::shared_ptr round; std::shared_ptr roundRect; void show(Canvas & to) override; void showAll(Canvas & to) override; void showPopupWindow(const Point & cursorPosition) override; bool isBoundUnitHighlighted() const; public: StackBox(StackQueue * owner); void setUnit(const battle::Unit * unit, size_t turn = 0, std::optional currentTurn = std::nullopt); std::optional getBoundUnitID() const; }; static const int QUEUE_SIZE_BIG = 10; std::shared_ptr background; std::vector> stackBoxes; BattleInterface & owner; int32_t getSiegeShooterIconID(); public: const bool embedded; StackQueue(bool Embedded, BattleInterface & owner); void update(); std::optional getHoveredUnitIdIfAny() const; void show(Canvas & to) override; };