2022-11-17 23:57:51 +02:00
|
|
|
/*
|
2022-12-11 23:16:23 +02:00
|
|
|
* BattleFieldController.h, part of VCMI engine
|
2022-11-17 23:57:51 +02:00
|
|
|
*
|
|
|
|
* 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/BattleHex.h"
|
2023-05-31 12:08:12 +02:00
|
|
|
#include "../../lib/Point.h"
|
2022-11-17 23:57:51 +02:00
|
|
|
#include "../gui/CIntObject.h"
|
|
|
|
|
2022-11-29 02:00:08 +02:00
|
|
|
VCMI_LIB_NAMESPACE_BEGIN
|
|
|
|
class CStack;
|
2023-01-17 22:01:35 +02:00
|
|
|
class Rect;
|
2023-01-18 17:32:57 +02:00
|
|
|
VCMI_LIB_NAMESPACE_END
|
|
|
|
|
2022-12-21 17:02:53 +02:00
|
|
|
class BattleHero;
|
2022-12-11 22:09:57 +02:00
|
|
|
class Canvas;
|
2022-11-25 11:46:47 +02:00
|
|
|
class IImage;
|
2022-12-09 13:26:17 +02:00
|
|
|
class BattleInterface;
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2022-12-11 23:16:23 +02:00
|
|
|
/// Handles battlefield grid as well as rendering of background layer of battle interface
|
2022-12-09 13:26:17 +02:00
|
|
|
class BattleFieldController : public CIntObject
|
2022-11-17 23:57:51 +02:00
|
|
|
{
|
2022-12-13 13:58:16 +02:00
|
|
|
BattleInterface & owner;
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2022-11-25 11:46:47 +02:00
|
|
|
std::shared_ptr<IImage> background;
|
|
|
|
std::shared_ptr<IImage> cellBorder;
|
2023-03-22 22:51:00 +02:00
|
|
|
std::shared_ptr<IImage> cellUnitMovementHighlight;
|
2023-04-04 21:34:56 +02:00
|
|
|
std::shared_ptr<IImage> cellUnitMaxMovementHighlight;
|
2022-11-25 11:46:47 +02:00
|
|
|
std::shared_ptr<IImage> cellShade;
|
2023-06-12 23:16:38 +02:00
|
|
|
std::shared_ptr<CAnimation> rangedFullDamageLimitImages;
|
|
|
|
std::shared_ptr<CAnimation> shootingRangeLimitImages;
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2023-06-01 16:49:42 +02:00
|
|
|
std::shared_ptr<CAnimation> attackCursors;
|
2023-09-06 22:01:43 +02:00
|
|
|
std::shared_ptr<CAnimation> spellCursors;
|
2023-06-01 16:49:42 +02:00
|
|
|
|
2022-11-25 11:46:47 +02:00
|
|
|
/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
|
2022-12-11 22:09:57 +02:00
|
|
|
std::unique_ptr<Canvas> backgroundWithHexes;
|
2022-11-25 11:46:47 +02:00
|
|
|
|
2023-05-30 23:33:10 +02:00
|
|
|
/// direction which will be used to perform attack with current cursor position
|
2023-05-31 12:08:12 +02:00
|
|
|
Point currentAttackOriginPoint;
|
2023-05-30 23:33:10 +02:00
|
|
|
|
|
|
|
/// hex currently under mouse hover
|
|
|
|
BattleHex hoveredHex;
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2022-12-11 23:16:23 +02:00
|
|
|
/// hexes to which currently active stack can move
|
2023-04-05 23:04:40 +02:00
|
|
|
std::vector<BattleHex> occupiableHexes;
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2022-12-11 23:16:23 +02:00
|
|
|
/// hexes that when in front of a unit cause it's amount box to move back
|
|
|
|
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
|
|
|
|
|
2023-04-04 21:34:56 +02:00
|
|
|
void showHighlightedHex(Canvas & to, std::shared_ptr<IImage> highlight, BattleHex hex, bool darkBorder);
|
2022-11-25 11:46:47 +02:00
|
|
|
|
2023-03-22 22:51:00 +02:00
|
|
|
std::set<BattleHex> getHighlightedHexesForActiveStack();
|
|
|
|
std::set<BattleHex> getMovementRangeForHoveredStack();
|
|
|
|
std::set<BattleHex> getHighlightedHexesForSpellRange();
|
2023-04-20 23:24:37 +02:00
|
|
|
std::set<BattleHex> getHighlightedHexesForMovementTarget();
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2023-06-18 21:09:50 +02:00
|
|
|
// Range limit highlight helpers
|
2023-06-18 11:45:36 +02:00
|
|
|
|
2023-06-17 21:15:40 +02:00
|
|
|
/// get all hexes within a certain distance of given hex
|
|
|
|
std::vector<BattleHex> getRangeHexes(BattleHex sourceHex, uint8_t distance);
|
2023-06-12 23:16:38 +02:00
|
|
|
|
2023-06-17 20:29:04 +02:00
|
|
|
/// get only hexes at the limit of a range
|
|
|
|
std::vector<BattleHex> getRangeLimitHexes(BattleHex hoveredHex, std::vector<BattleHex> hexRange, uint8_t distanceToLimit);
|
2023-06-12 23:16:38 +02:00
|
|
|
|
2023-06-18 11:45:36 +02:00
|
|
|
/// calculate if a hex is in range limit and return its index in range
|
2023-06-23 18:50:39 +02:00
|
|
|
bool IsHexInRangeLimit(BattleHex hex, std::vector<BattleHex> & rangeLimitHexes, int * hexIndexInRangeLimit);
|
2023-06-18 11:45:36 +02:00
|
|
|
|
2023-05-14 20:07:47 +02:00
|
|
|
/// get an array that has for each hex in range, an aray with all directions where an ouside neighbour hex exists
|
2023-06-23 18:50:39 +02:00
|
|
|
std::vector<std::vector<BattleHex::EDir>> getOutsideNeighbourDirectionsForLimitHexes(std::vector<BattleHex> rangeHexes, std::vector<BattleHex> rangeLimitHexes);
|
2023-05-14 20:07:47 +02:00
|
|
|
|
|
|
|
/// calculates what image to use as range limit, depending on the direction of neighbors
|
|
|
|
/// a mask is used internally to mark the directions of all neighbours
|
|
|
|
/// based on this mask the corresponding image is selected
|
2023-06-18 11:45:36 +02:00
|
|
|
std::vector<std::shared_ptr<IImage>> calculateRangeLimitHighlightImages(std::vector<std::vector<BattleHex::EDir>> hexesNeighbourDirections, std::shared_ptr<CAnimation> limitImages);
|
2023-05-14 20:07:47 +02:00
|
|
|
|
2023-06-18 11:03:12 +02:00
|
|
|
/// calculates all hexes for a range limit and what images to be shown as highlight for each of the hexes
|
2023-06-23 18:50:39 +02:00
|
|
|
void calculateRangeLimitAndHighlightImages(uint8_t distance, std::shared_ptr<CAnimation> rangeLimitImages, std::vector<BattleHex> & rangeLimitHexes, std::vector<std::shared_ptr<IImage>> & rangeLimitHexesHighligts);
|
2023-06-18 11:03:12 +02:00
|
|
|
|
2023-05-25 21:36:42 +02:00
|
|
|
/// to reduce the number of source images used, some images will be used as flipped versions of preloaded ones
|
2023-06-18 11:45:36 +02:00
|
|
|
void flipRangeLimitImagesIntoPositions(std::shared_ptr<CAnimation> images);
|
|
|
|
|
2022-12-11 22:09:57 +02:00
|
|
|
void showBackground(Canvas & canvas);
|
|
|
|
void showBackgroundImage(Canvas & canvas);
|
|
|
|
void showBackgroundImageWithHexes(Canvas & canvas);
|
|
|
|
void showHighlightedHexes(Canvas & canvas);
|
2023-03-29 12:03:40 +02:00
|
|
|
void updateAccessibleHexes();
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2023-05-30 23:33:10 +02:00
|
|
|
BattleHex getHexAtPosition(Point hoverPosition);
|
|
|
|
|
|
|
|
/// Checks whether selected pixel is transparent, uses local coordinates of a hex
|
|
|
|
bool isPixelInHex(Point const & position);
|
2023-06-01 16:49:42 +02:00
|
|
|
size_t selectBattleCursor(BattleHex myNumber);
|
2022-12-21 17:02:53 +02:00
|
|
|
|
2023-06-16 11:54:07 +02:00
|
|
|
void gesture(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
2023-05-30 23:33:10 +02:00
|
|
|
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
|
2023-06-22 21:11:48 +02:00
|
|
|
void mouseMoved(const Point & cursorPosition, const Point & lastUpdateDistance) override;
|
2023-07-09 16:48:25 +02:00
|
|
|
void clickPressed(const Point & cursorPosition) override;
|
2023-07-08 13:33:04 +02:00
|
|
|
void showPopupWindow(const Point & cursorPosition) override;
|
2023-05-13 17:00:14 +02:00
|
|
|
void activate() override;
|
2023-01-29 14:34:47 +02:00
|
|
|
|
2023-06-02 15:42:18 +02:00
|
|
|
void showAll(Canvas & to) override;
|
|
|
|
void show(Canvas & to) override;
|
2023-05-13 22:38:57 +02:00
|
|
|
void tick(uint32_t msPassed) override;
|
2023-05-29 12:08:08 +02:00
|
|
|
|
|
|
|
bool receiveEvent(const Point & position, int eventType) const override;
|
2023-05-30 23:33:10 +02:00
|
|
|
|
2022-11-27 23:42:18 +02:00
|
|
|
public:
|
2022-12-13 13:58:16 +02:00
|
|
|
BattleFieldController(BattleInterface & owner);
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2022-12-21 17:02:53 +02:00
|
|
|
void createHeroes();
|
|
|
|
|
2022-11-27 23:42:18 +02:00
|
|
|
void redrawBackgroundWithHexes();
|
2022-12-11 22:09:57 +02:00
|
|
|
void renderBattlefield(Canvas & canvas);
|
2022-11-17 23:57:51 +02:00
|
|
|
|
2022-12-11 23:16:23 +02:00
|
|
|
/// Returns position of hex relative to owner (BattleInterface)
|
2022-11-25 11:46:47 +02:00
|
|
|
Rect hexPositionLocal(BattleHex hex) const;
|
2022-12-11 23:16:23 +02:00
|
|
|
|
|
|
|
/// Returns position of hex relative to game window
|
|
|
|
Rect hexPositionAbsolute(BattleHex hex) const;
|
|
|
|
|
|
|
|
/// Returns ID of currently hovered hex or BattleHex::INVALID if none
|
2022-11-17 23:57:51 +02:00
|
|
|
BattleHex getHoveredHex();
|
|
|
|
|
2023-06-17 20:29:04 +02:00
|
|
|
/// Returns the currently hovered stack
|
|
|
|
const CStack* getHoveredStack();
|
|
|
|
|
2022-12-11 23:16:23 +02:00
|
|
|
/// returns true if selected tile can be attacked in melee by current stack
|
2022-11-17 23:57:51 +02:00
|
|
|
bool isTileAttackable(const BattleHex & number) const;
|
2022-12-11 23:16:23 +02:00
|
|
|
|
|
|
|
/// returns true if stack should render its stack count image in default position - outside own hex
|
2022-11-17 23:57:51 +02:00
|
|
|
bool stackCountOutsideHex(const BattleHex & number) const;
|
2022-12-11 23:16:23 +02:00
|
|
|
|
2023-06-01 16:49:42 +02:00
|
|
|
BattleHex::EDir selectAttackDirection(BattleHex myNumber);
|
|
|
|
|
2022-12-11 23:16:23 +02:00
|
|
|
BattleHex fromWhichHexAttack(BattleHex myNumber);
|
2022-11-17 23:57:51 +02:00
|
|
|
};
|