1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141
|
/*
* BattleFieldController.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 "../../lib/battle/BattleHexArray.h"
#include "../../lib/Point.h"
#include "../gui/CIntObject.h"
VCMI_LIB_NAMESPACE_BEGIN
class CStack;
class Rect;
VCMI_LIB_NAMESPACE_END
class BattleHero;
class CAnimation;
class Canvas;
class IImage;
class BattleInterface;
/// Handles battlefield grid as well as rendering of background layer of battle interface
class BattleFieldController : public CIntObject
{
BattleInterface & owner;
std::shared_ptr<IImage> background;
std::shared_ptr<IImage> cellBorder;
std::shared_ptr<IImage> cellUnitMovementHighlight;
std::shared_ptr<IImage> cellUnitMaxMovementHighlight;
std::shared_ptr<IImage> cellShade;
std::shared_ptr<CAnimation> rangedFullDamageLimitImages;
std::shared_ptr<CAnimation> shootingRangeLimitImages;
std::shared_ptr<CAnimation> attackCursors;
std::shared_ptr<CAnimation> spellCursors;
/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
std::unique_ptr<Canvas> backgroundWithHexes;
/// direction which will be used to perform attack with current cursor position
Point currentAttackOriginPoint;
/// hex currently under mouse hover
BattleHex hoveredHex;
/// hexes to which currently active stack can move
BattleHexArray occupiableHexes;
/// hexes that when in front of a unit cause it's amount box to move back
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
void showHighlightedHex(Canvas & to, std::shared_ptr<IImage> highlight, const BattleHex & hex, bool darkBorder);
BattleHexArray getHighlightedHexesForActiveStack();
BattleHexArray getMovementRangeForHoveredStack();
BattleHexArray getHighlightedHexesForSpellRange();
BattleHexArray getHighlightedHexesForMovementTarget();
// Range limit highlight helpers
/// get all hexes within a certain distance of given hex
BattleHexArray getRangeHexes(const BattleHex & sourceHex, uint8_t distance);
/// get only hexes at the limit of a range
BattleHexArray getRangeLimitHexes(const BattleHex & hoveredHex, const BattleHexArray & hexRange, uint8_t distanceToLimit);
/// calculate if a hex is in range limit and return its index in range
bool IsHexInRangeLimit(const BattleHex & hex, const BattleHexArray & rangeLimitHexes, int * hexIndexInRangeLimit);
/// get an array that has for each hex in range, an array with all directions where an outside neighbour hex exists
std::vector<std::vector<BattleHex::EDir>> getOutsideNeighbourDirectionsForLimitHexes(const BattleHexArray & rangeHexes, const BattleHexArray & rangeLimitHexes);
/// calculates what image to use as range limit, depending on the direction of neighbours
/// a mask is used internally to mark the directions of all neighbours
/// based on this mask the corresponding image is selected
std::vector<std::shared_ptr<IImage>> calculateRangeLimitHighlightImages(std::vector<std::vector<BattleHex::EDir>> hexesNeighbourDirections, std::shared_ptr<CAnimation> limitImages);
/// calculates all hexes for a range limit and what images to be shown as highlight for each of the hexes
void calculateRangeLimitAndHighlightImages(uint8_t distance, std::shared_ptr<CAnimation> rangeLimitImages, BattleHexArray & rangeLimitHexes, std::vector<std::shared_ptr<IImage>> & rangeLimitHexesHighlights);
void showBackground(Canvas & canvas);
void showBackgroundImage(Canvas & canvas);
void showBackgroundImageWithHexes(Canvas & canvas);
void showHighlightedHexes(Canvas & canvas);
void updateAccessibleHexes();
BattleHex getHexAtPosition(Point hoverPosition);
/// Checks whether selected pixel is transparent, uses local coordinates of a hex
bool isPixelInHex(Point const & position);
size_t selectBattleCursor(const BattleHex & myNumber);
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override;
void clickPressed(const Point & cursorPosition) override;
void showPopupWindow(const Point & cursorPosition) override;
void activate() override;
void showAll(Canvas & to) override;
void show(Canvas & to) override;
void tick(uint32_t msPassed) override;
bool receiveEvent(const Point & position, int eventType) const override;
public:
BattleFieldController(BattleInterface & owner);
void createHeroes();
void redrawBackgroundWithHexes();
void renderBattlefield(Canvas & canvas);
/// Returns position of hex relative to owner (BattleInterface)
Rect hexPositionLocal(const BattleHex & hex) const;
/// Returns position of hex relative to game window
Rect hexPositionAbsolute(const BattleHex & hex) const;
/// Returns ID of currently hovered hex or BattleHex::INVALID if none
BattleHex getHoveredHex();
/// Returns the currently hovered stack
const CStack* getHoveredStack();
/// returns true if selected tile can be attacked in melee by current stack
bool isTileAttackable(const BattleHex & number) const;
/// returns true if stack should render its stack count image in default position - outside own hex
bool stackCountOutsideHex(const BattleHex & number) const;
BattleHex::EDir selectAttackDirection(const BattleHex & myNumber);
BattleHex fromWhichHexAttack(const BattleHex & myNumber);
};
|