Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions src/fheroes2/battle/battle_cell.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -173,6 +173,12 @@ Battle::Position Battle::Position::GetReachable( const Unit & unit, const int32_
return {};
};

Position headPos = tryHead();

if ( headPos.GetHead() != nullptr && headPos.GetTail() != nullptr ) {
return headPos;
}

const auto tryTail = [&unit, dst, &checkCells]() -> Position {
const CellDirection headDirection = unit.isReflect() ? CellDirection::LEFT : CellDirection::RIGHT;

Expand All @@ -186,12 +192,6 @@ Battle::Position Battle::Position::GetReachable( const Unit & unit, const int32_
return {};
};

Position headPos = tryHead();

if ( headPos.GetHead() != nullptr && headPos.GetTail() != nullptr ) {
return headPos;
}

return tryTail();
}

Expand Down
93 changes: 82 additions & 11 deletions src/fheroes2/battle/battle_interface.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1182,7 +1182,7 @@ void Battle::Status::clear()
_lastMessage = "";
}

bool Battle::TurnOrder::queueEventProcessing( Interface & interface, std::string & msg, const fheroes2::Point & offset ) const
bool Battle::TurnOrder::queueEventProcessing( Interface & interface, std::string & msg, const fheroes2::Point & offset, const bool highlightUnitMomevementArea ) const
{
LocalEvent & le = LocalEvent::Get();

Expand All @@ -1196,6 +1196,10 @@ bool Battle::TurnOrder::queueEventProcessing( Interface & interface, std::string

interface.setUnitTobeHighlighted( unit );

if ( highlightUnitMomevementArea ) {
interface.setUnitToShowMovementArea( unit );
}

// Process mouse buttons events.
if ( le.MouseClickLeft( unitRoi ) ) {
Dialog::ArmyInfo( *unit, Dialog::BUTTONS, unit->isReflect() );
Expand Down Expand Up @@ -1431,6 +1435,7 @@ Battle::Interface::Interface( Arena & battleArena, const int32_t tileIndex )
_hexagonShadow = DrawHexagonShadow( 4, 2 );
// Shadow that fits the hexagon grid.
_hexagonGridShadow = DrawHexagonShadow( 4, 1 );
_hexagonHighlightShadow = DrawHexagonShadow( 2, 2 );

_buttonAuto.setICNInfo( ICN::TEXTBAR, 4, 5 );
_buttonSettings.setICNInfo( ICN::TEXTBAR, 6, 7 );
Expand Down Expand Up @@ -2392,21 +2397,79 @@ void Battle::Interface::_redrawCoverStatic()
{
fheroes2::Copy( _battleGround, _mainSurface );

if ( _movingUnit != nullptr ) {
// Do not show movement area while units are in action.
return;
}

const Settings & conf = Settings::Get();
if ( !conf.BattleShowMoveShadow() ) {
// Display movement area only if the associated option is enabled.
return;
}

// Movement shadow.
if ( !_movingUnit && conf.BattleShowMoveShadow() && _currentUnit && !( _currentUnit->GetCurrentControl() & CONTROL_AI ) ) {
const fheroes2::Image & shadowImage = conf.BattleShowGrid() ? _hexagonGridShadow : _hexagonShadow;
const Board & board = *Arena::GetBoard();
if ( _currentUnit == nullptr || ( _currentUnit->GetCurrentControl() & CONTROL_AI ) ) {
// No current unit is selected or this unit is controlled by AI.
return;
}

Board & board = *Arena::GetBoard();

std::array<bool, Board::sizeInCells> processedCells{ false };
assert( board.size() == processedCells.size() );

if ( _highlightUnitMovementArea != nullptr ) {
Unit * foundUnit = nullptr;
for ( Cell & cell : board ) {
Unit * unit = cell.GetUnit();
if ( unit != nullptr && unit == _highlightUnitMovementArea ) {
foundUnit = unit;
break;
}
}

// If we hit this assertion then the unit doesn't even exist.
assert( foundUnit != nullptr );

// The highlighted unit might have moved. We want to display the real movement area.
const bool isMoved = foundUnit->Modes( Battle::TR_MOVED );

foundUnit->ResetModes( Battle::TR_MOVED );

// To avoid pathfinder re-evaluation we need to run the same loop separately for the selected unit and then for the current unit.
// In this case we do re-evaluation only once.
for ( const Cell & cell : board ) {
const Position pos = Position::GetReachable( *_currentUnit, cell.GetIndex() );
const Position pos = Position::GetReachable( *_highlightUnitMovementArea, cell.GetIndex() );

if ( pos.GetHead() != nullptr ) {
assert( pos.isValidForUnit( _currentUnit ) );
assert( pos.isValidForUnit( _highlightUnitMovementArea ) );

fheroes2::Blit( shadowImage, _mainSurface, cell.GetPos().x, cell.GetPos().y );
// To separate enemy movement from the current unit we apply the shadow twice.
fheroes2::Blit( _hexagonHighlightShadow, _mainSurface, cell.GetPos().x, cell.GetPos().y );
fheroes2::Blit( _hexagonHighlightShadow, _mainSurface, cell.GetPos().x, cell.GetPos().y );

processedCells[cell.GetIndex()] = true;
}
}

if ( isMoved ) {
foundUnit->SetModes( Battle::TR_MOVED );
}
}

const fheroes2::Image & shadowImage = conf.BattleShowGrid() ? _hexagonGridShadow : _hexagonShadow;

for ( const Cell & cell : board ) {
if ( processedCells[cell.GetIndex()] ) {
continue;
}

const Position pos = Position::GetReachable( *_currentUnit, cell.GetIndex() );
if ( pos.GetHead() != nullptr ) {
assert( pos.isValidForUnit( _currentUnit ) );

fheroes2::Blit( shadowImage, _mainSurface, cell.GetPos().x, cell.GetPos().y );
}
}
}

Expand Down Expand Up @@ -2689,7 +2752,7 @@ void Battle::Interface::RedrawKilled()
}
}

int Battle::Interface::GetBattleCursor( std::string & statusMsg ) const
int Battle::Interface::GetBattleCursor( std::string & statusMsg, const bool highlightUnitMomevementArea )
{
statusMsg.clear();

Expand All @@ -2707,6 +2770,10 @@ int Battle::Interface::GetBattleCursor( std::string & statusMsg ) const

const Unit * unit = cell->GetUnit();

if ( highlightUnitMomevementArea ) {
_highlightUnitMovementArea = unit;
}

if ( unit == nullptr || _currentUnit == unit ) {
const Position pos = Position::GetReachable( *_currentUnit, _currentCellIndex );
if ( pos.GetHead() != nullptr ) {
Expand Down Expand Up @@ -2978,6 +3045,10 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s

BoardActionIntentUpdater boardActionIntentUpdater( _boardActionIntent, le.isMouseEventFromTouchpad() );

// Make sure to reset currently selected unit every time we do rendering.
_highlightUnitMovementArea = nullptr;
const bool highlightUnitMovementArea = Game::HotKeyHoldEvent( Game::HotKeyEvent::BATTLE_HIGHLIGHT_UNIT_AREA_MODIFIER );

_buttonAuto.drawOnState( le.isMouseLeftButtonPressedAndHeldInArea( _buttonAuto.area() ) );
_buttonSettings.drawOnState( le.isMouseLeftButtonPressedAndHeldInArea( _buttonSettings.area() ) );
_buttonSkip.drawOnState( le.isMouseLeftButtonPressedAndHeldInArea( _buttonSkip.area() ) );
Expand Down Expand Up @@ -3069,7 +3140,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
}
else if ( conf.BattleShowTurnOrder() && le.isMouseCursorPosInArea( _turnOrder.getRenderingRoi() ) ) {
cursor.SetThemes( Cursor::POINTER );
if ( _turnOrder.queueEventProcessing( *this, msg, _interfacePosition.getPosition() ) ) {
if ( _turnOrder.queueEventProcessing( *this, msg, _interfacePosition.getPosition(), highlightUnitMovementArea ) ) {
humanturn_redraw = true;
}
}
Expand Down Expand Up @@ -3193,7 +3264,7 @@ void Battle::Interface::HumanBattleTurn( const Unit & unit, Actions & actions, s
}
}
else if ( le.isMouseCursorPosInArea( battleFieldRect ) ) {
int themes = GetBattleCursor( msg );
int themes = GetBattleCursor( msg, highlightUnitMovementArea );

if ( _swipeAttack.isValid() ) {
// The swipe attack motion is either in progress or has finished.
Expand Down
11 changes: 9 additions & 2 deletions src/fheroes2/battle/battle_interface.h
Original file line number Diff line number Diff line change
Expand Up @@ -243,7 +243,7 @@ namespace Battle

void redraw( const Unit * current, const uint8_t currentUnitColor, const Unit * underCursor, fheroes2::Image & output, const fheroes2::Rect & dialogRoi );

bool queueEventProcessing( Interface & interface, std::string & msg, const fheroes2::Point & offset ) const;
bool queueEventProcessing( Interface & interface, std::string & msg, const fheroes2::Point & offset, const bool highlightUnitMomevementArea ) const;

const fheroes2::Rect & getRenderingRoi() const
{
Expand Down Expand Up @@ -351,6 +351,11 @@ namespace Battle
_unitToHighlight = unit;
}

void setUnitToShowMovementArea( const Unit * unit )
{
_highlightUnitMovementArea = unit;
}

void SetOrderOfUnits( const std::shared_ptr<const Units> & units );
void FadeArena( const bool clearMessageLog );

Expand Down Expand Up @@ -459,7 +464,7 @@ namespace Battle
void MouseLeftClickBoardAction( const int themes, const Cell & cell, const bool isConfirmed, Actions & actions );
bool MousePressRightBoardAction( const Cell & cell ) const;

int GetBattleCursor( std::string & statusMsg ) const;
int GetBattleCursor( std::string & statusMsg, const bool highlightUnitMomevementArea );
int GetBattleSpellCursor( std::string & statusMsg ) const;

void _startAutoCombat( const Unit & unit, Actions & actions );
Expand All @@ -476,6 +481,7 @@ namespace Battle
fheroes2::Image _hexagonShadow;
fheroes2::Image _hexagonGridShadow;
fheroes2::Image _hexagonCursorShadow;
fheroes2::Image _hexagonHighlightShadow;

int _battleGroundIcn{ ICN::UNKNOWN };
int _borderObjectsIcn{ ICN::UNKNOWN };
Expand Down Expand Up @@ -509,6 +515,7 @@ namespace Battle
const Unit * _movingUnit{ nullptr };
const Unit * _flyingUnit{ nullptr };
const Unit * _unitToHighlight{ nullptr };
const Unit * _highlightUnitMovementArea{ nullptr };
const fheroes2::Sprite * _spriteInsteadCurrentUnit{ nullptr };
fheroes2::Point _movingPos;
fheroes2::Point _flyingPos;
Expand Down
2 changes: 2 additions & 0 deletions src/fheroes2/game/game_hotkeys.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -298,6 +298,8 @@ namespace
= { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|cast battle spell" ), fheroes2::Key::KEY_C };
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_TOGGLE_TURN_ORDER_DISPLAY )]
= { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|toggle display of battle turn order" ), fheroes2::Key::KEY_T };
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::BATTLE_HIGHLIGHT_UNIT_AREA_MODIFIER )]
= { Game::HotKeyCategory::BATTLE, gettext_noop( "hotkey|hold to highlight unit movement area" ), fheroes2::Key::KEY_LEFT_SHIFT };

hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::TOWN_DWELLING_LEVEL_1 )]
= { Game::HotKeyCategory::TOWN, gettext_noop( "hotkey|dwelling level 1" ), fheroes2::Key::KEY_1 };
Expand Down
1 change: 1 addition & 0 deletions src/fheroes2/game/game_hotkeys.h
Original file line number Diff line number Diff line change
Expand Up @@ -156,6 +156,7 @@ namespace Game
BATTLE_SKIP,
BATTLE_CAST_SPELL,
BATTLE_TOGGLE_TURN_ORDER_DISPLAY,
BATTLE_HIGHLIGHT_UNIT_AREA_MODIFIER,

TOWN_DWELLING_LEVEL_1,
TOWN_DWELLING_LEVEL_2,
Expand Down
Loading