Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add swap army and swap artifacts to the heroes meeting screen #9387

Merged
merged 19 commits into from
Dec 30, 2024
Merged
Show file tree
Hide file tree
Changes from 15 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
119 changes: 119 additions & 0 deletions src/fheroes2/agg/agg_image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -3232,6 +3232,125 @@ namespace

return true;
}
case ICN::SWAP_ARROWS_CIRCULAR: {
const fheroes2::Sprite & original = fheroes2::AGG::GetICN( ICN::SWAP_ARROW_LEFT_TO_RIGHT, 0 );

const int32_t width = 47;
const int32_t height = 42;
fheroes2::Image out;
out.resize( width, height );
out.reset();

// Rotate arrow heads.
const int32_t arrowTipToShaftLength = 18;
const int32_t arrowHeadWidth = 20;

fheroes2::Image rotatedArrow;
rotatedArrow.resize( arrowHeadWidth, arrowTipToShaftLength );
rotatedArrow.reset();
for ( int x = 0; x < arrowTipToShaftLength; ++x ) {
for ( int y = 0; y < arrowHeadWidth; ++y ) {
Copy( original, x + ( original.width() - arrowTipToShaftLength ), y, rotatedArrow, arrowHeadWidth - y - 1, arrowTipToShaftLength - x - 1, 1, 1 );
}
}

fheroes2::Copy( Flip( rotatedArrow, true, true ), 0, 0, out, 0, 5, arrowHeadWidth, arrowTipToShaftLength );
fheroes2::Copy( Flip( rotatedArrow, true, false ), 0, 0, out, 27, 19, arrowHeadWidth, arrowTipToShaftLength );

// Rotate arrow ends.
const int32_t arrowEndHeight = 11;
const int32_t arrowEndWidth = 9;

rotatedArrow.resize( arrowEndWidth, arrowEndHeight );
rotatedArrow.reset();

for ( int x = 0; x < arrowEndHeight; ++x ) {
for ( int y = 0; y < arrowEndWidth; ++y ) {
Copy( original, x + 2, y + 5, rotatedArrow, arrowEndWidth - y - 1, arrowEndHeight - x - 1, 1, 1 );
}
}

// Clean black corner.
fheroes2::Copy( original, 0, 0, rotatedArrow, 0, rotatedArrow.height() - 1, 1, 1 );

fheroes2::Copy( rotatedArrow, 0, 0, out, 32, 6, arrowEndWidth, arrowEndHeight );
fheroes2::Copy( Flip( rotatedArrow, false, true ), 0, 0, out, 5, 25, arrowEndWidth, arrowEndHeight );

// Add straight shafts.
Copy( original, 5, 5, out, 13, 0, 21, 10 );
Copy( original, 5, 5, out, 12, 32, 22, 10 );

// Lower arrow.
// Fix overlaps.
fheroes2::SetPixel( out, out.width() - 9, out.height() - 5, 119 );
fheroes2::DrawLine( out, { out.width() - 13, out.height() - 6 }, { out.width() - 12, out.height() - 6 }, 109 );
fheroes2::SetPixel( out, 12, out.height() - 10, 119 );
fheroes2::SetPixel( out, out.width() - 14, out.height() - 10, 119 );

// Lower right corner.
Copy( original, 5, 10, out, out.width() - 13, out.height() - 5, 4, 5 );
fheroes2::DrawLine( out, { out.width() - 6, out.height() - 4 }, { out.width() - 9, out.height() - 1 }, 59 );
fheroes2::DrawLine( out, { out.width() - 6, out.height() - 5 }, { out.width() - 9, out.height() - 2 }, 59 );
fheroes2::DrawLine( out, { out.width() - 7, out.height() - 5 }, { out.width() - 9, out.height() - 3 }, 129 );
fheroes2::DrawLine( out, { out.width() - 8, out.height() - 5 }, { out.width() - 9, out.height() - 4 }, 123 );
fheroes2::SetPixel( out, out.width() - 9, out.height() - 5, 119 );
fheroes2::SetPixel( out, out.width() - 11, out.height() - 6, 112 );

// Lower left corner.
Copy( original, 5, 9, out, 9, out.height() - 6, 3, 6 );
Copy( rotatedArrow, 0, 0, out, 5, out.height() - 7, 4, 2 );
fheroes2::DrawLine( out, { 5, out.height() - 5 }, { 8, out.height() - 2 }, 129 );
fheroes2::DrawLine( out, { 6, out.height() - 5 }, { 8, out.height() - 3 }, 123 );
fheroes2::DrawLine( out, { 7, out.height() - 5 }, { 8, out.height() - 4 }, 119 );
fheroes2::SetPixel( out, 8, out.height() - 5, 116 );
fheroes2::SetPixel( out, 9, out.height() - 6, 112 );

// Fix shading.
fheroes2::DrawLine( out, { 14, out.height() - 15 }, { 14, out.height() - 11 }, 59 );

// Upper arrow.
// Upper left corner.
fheroes2::Copy( out, 15, 0, out, 9, 0, 4, 5 );
fheroes2::Copy( out, 21, 5, out, 11, 5, 3, 2 );
fheroes2::DrawLine( out, { 8, 1 }, { 5, 4 }, 129 );
fheroes2::DrawLine( out, { 8, 2 }, { 6, 4 }, 119 );
fheroes2::DrawLine( out, { 8, 3 }, { 7, 4 }, 114 );
fheroes2::SetPixel( out, 8, 4, 112 );
fheroes2::SetPixel( out, 9, 4, 112 );

// Upper right corner.
fheroes2::Copy( out, 21, 0, out, 33, 0, 3, 6 );
fheroes2::Copy( out, 36, 7, out, 36, 5, 5, 1 );
fheroes2::Copy( out, 37, 6, out, 37, 4, 3, 1 );
fheroes2::Copy( out, 37, 6, out, 37, 4, 3, 1 );
fheroes2::Copy( out, 34, 1, out, 36, 1, 1, 3 );
fheroes2::DrawLine( out, { 36, 0 }, { 40, 4 }, 129 );
fheroes2::DrawLine( out, { 37, 2 }, { 38, 3 }, 119 );
fheroes2::DrawLine( out, { 36, 4 }, { 37, 3 }, 113 );

// Fix overlap.
fheroes2::DrawLine( out, { 33, 8 }, { 33, 9 }, 123 );
fheroes2::SetPixel( out, 32, 9, 129 );
fheroes2::SetPixel( out, 13, 9, 129 );

// Fix shading.
fheroes2::DrawLine( out, { 10, 22 }, { 18, 14 }, 59 );
fheroes2::DrawLine( out, { 11, 22 }, { 19, 14 }, 59 );
fheroes2::DrawLine( out, { 34, 17 }, { 40, 17 }, 59 );
fheroes2::DrawLine( out, { 41, 5 }, { 41, 16 }, 59 );
fheroes2::SetPixel( out, 40, 16, 59 );
fheroes2::Copy( original, 0, 0, out, 1, 12, 4, 1 );
fheroes2::Copy( original, 0, 0, out, 15, 12, 5, 1 );

// Make pressed state.
_icnVsSprite[id].resize( 2 );
_icnVsSprite[id][0] = out;
_icnVsSprite[id][1] = _icnVsSprite[id][0];
_icnVsSprite[id][1].setPosition( -1, 1 );
ApplyPalette( _icnVsSprite[id][1], 4 );

return true;
}
case ICN::EDITBTNS:
LoadOriginalICN( id );
if ( _icnVsSprite[id].size() == 35 ) {
Expand Down
1 change: 1 addition & 0 deletions src/fheroes2/agg/icn.h
Original file line number Diff line number Diff line change
Expand Up @@ -944,6 +944,7 @@ namespace ICN
SILVER_GRADIENT_LARGE_FONT,
SWAP_ARROW_LEFT_TO_RIGHT,
SWAP_ARROW_RIGHT_TO_LEFT,
SWAP_ARROWS_CIRCULAR,

COLOR_CURSOR_ADVENTURE_MAP,
MONO_CURSOR_ADVENTURE_MAP,
Expand Down
8 changes: 8 additions & 0 deletions src/fheroes2/army/army.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1509,6 +1509,14 @@ void Army::MoveTroops( Army & from, const int monsterIdToKeep )
moveTroops( false );
}

void Army::SwapTroops( Army & from )
{
assert( this != &from );
const Troops temp = this->getTroops();
Assign( from );
from.Assign( temp );
}

uint32_t Army::ActionToSirens() const
{
uint32_t experience = 0;
Expand Down
4 changes: 3 additions & 1 deletion src/fheroes2/army/army.h
Original file line number Diff line number Diff line change
Expand Up @@ -228,8 +228,10 @@ class Army final : public Troops, public Control

void JoinStrongestFromArmy( Army & giver );

// Implements the necessary logic to move unit stacks from army to army in the hero's meeting dialog and in the castle dialog
// Implements the necessary logic to move unit stacks from army to army in the heroes meeting dialog and in the castle dialog
void MoveTroops( Army & from, const int monsterIdToKeep );
// Implements the necessary logic to swap all unit stacks from an army to another army in the heroes meeting dialog and in the castle dialog
void SwapTroops( Army & from );

void SetSpreadFormation( const bool spread )
{
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 @@ -316,6 +316,8 @@ namespace
= { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|upgrade troop" ), fheroes2::Key::KEY_U };
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_DISMISS )]
= { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|dismiss hero or troop" ), fheroes2::Key::KEY_D };
hotKeyEventInfo[hotKeyEventToInt( Game::HotKeyEvent::ARMY_SWAP )]
= { Game::HotKeyCategory::ARMY, gettext_noop( "hotkey|exchange all troops" ), fheroes2::Key::KEY_S };
}

std::string getHotKeyFileContent()
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 @@ -163,6 +163,7 @@ namespace Game
ARMY_JOIN_STACKS,
ARMY_UPGRADE_TROOP,
ARMY_DISMISS,
ARMY_SWAP,

// WARNING! Put all new event only above this line. No adding in between.
NO_EVENT,
Expand Down
61 changes: 55 additions & 6 deletions src/fheroes2/heroes/heroes_meeting.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -346,11 +346,12 @@ void Heroes::MeetingDialog( Heroes & otherHero )
fheroes2::Blit( moveButtonBackground, 292, 270, display, cur_pt.x + 292, cur_pt.y + 270, 48, 44 );

// The original resources do not have such animated buttons so we have to create those.
fheroes2::ButtonSprite moveArmyToHero2 = createMoveButton( ICN::SWAP_ARROW_LEFT_TO_RIGHT, cur_pt.x + 298, cur_pt.y + 267, display );
fheroes2::ButtonSprite moveArmyToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 298, cur_pt.y + 290, display );
fheroes2::ButtonSprite moveArmyToHero2 = createMoveButton( ICN::SWAP_ARROW_LEFT_TO_RIGHT, cur_pt.x + 126, cur_pt.y + 319, display );
fheroes2::ButtonSprite moveArmyToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 472, cur_pt.y + 319, display );
fheroes2::ButtonSprite swapArmies = createMoveButton( ICN::SWAP_ARROWS_CIRCULAR, cur_pt.x + 297, cur_pt.y + 268, display );

fheroes2::ImageRestorer armyCountBackgroundRestorerLeft( display, cur_pt.x + 36, cur_pt.y + 310, 223, 20 );
fheroes2::ImageRestorer armyCountBackgroundRestorerRight( display, cur_pt.x + 381, cur_pt.y + 310, 223, 20 );
fheroes2::ImageRestorer armyCountBackgroundRestorerLeft( display, cur_pt.x + 36, cur_pt.y + 311, 223, 8 );
fheroes2::ImageRestorer armyCountBackgroundRestorerRight( display, cur_pt.x + 381, cur_pt.y + 311, 223, 8 );

// army
dst_pt.x = cur_pt.x + 36;
Expand Down Expand Up @@ -393,8 +394,9 @@ void Heroes::MeetingDialog( Heroes & otherHero )
selectArtifacts2.Redraw( display );

fheroes2::Blit( moveButtonBackground, 292, 363, display, cur_pt.x + 292, cur_pt.y + 363, 48, 44 );
fheroes2::ButtonSprite moveArtifactsToHero2 = createMoveButton( ICN::SWAP_ARROW_LEFT_TO_RIGHT, cur_pt.x + 298, cur_pt.y + 361, display );
fheroes2::ButtonSprite moveArtifactsToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 298, cur_pt.y + 384, display );
fheroes2::ButtonSprite moveArtifactsToHero2 = createMoveButton( ICN::SWAP_ARROW_LEFT_TO_RIGHT, cur_pt.x + 126, cur_pt.y + 426, display );
fheroes2::ButtonSprite moveArtifactsToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 472, cur_pt.y + 426, display );
fheroes2::ButtonSprite swapAllArtifacts = createMoveButton( ICN::SWAP_ARROWS_CIRCULAR, cur_pt.x + 297, cur_pt.y + 361, display );

// button exit
dst_pt.x = cur_pt.x + 280;
Expand All @@ -403,8 +405,10 @@ void Heroes::MeetingDialog( Heroes & otherHero )

moveArmyToHero2.draw();
moveArmyToHero1.draw();
swapArmies.draw();
moveArtifactsToHero2.draw();
moveArtifactsToHero1.draw();
swapAllArtifacts.draw();
buttonExit.draw();

// Fade-in heroes meeting dialog. Use half fade if game resolution is not 640x480.
Expand All @@ -428,9 +432,13 @@ void Heroes::MeetingDialog( Heroes & otherHero )
moveArmyToHero1.drawOnPress();
moveArmyToHero2.drawOnRelease();
}
else if ( le.isMouseLeftButtonPressedInArea( swapArmies.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SWAP ) ) {
swapArmies.drawOnPress();
}
else {
moveArmyToHero1.drawOnRelease();
moveArmyToHero2.drawOnRelease();
swapArmies.drawOnRelease();
}

if ( le.isMouseLeftButtonPressedInArea( moveArtifactsToHero2.area() ) ) {
Expand All @@ -441,9 +449,13 @@ void Heroes::MeetingDialog( Heroes & otherHero )
moveArtifactsToHero1.drawOnPress();
moveArtifactsToHero2.drawOnRelease();
}
else if ( le.isMouseLeftButtonPressedInArea( swapAllArtifacts.area() ) ) {
swapAllArtifacts.drawOnPress();
}
else {
moveArtifactsToHero1.drawOnRelease();
moveArtifactsToHero2.drawOnRelease();
swapAllArtifacts.drawOnRelease();
}

if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() )
Expand Down Expand Up @@ -616,6 +628,23 @@ void Heroes::MeetingDialog( Heroes & otherHero )

display.render();
}
else if ( le.MouseClickLeft( swapArmies.area() ) || HotKeyPressEvent( Game::HotKeyEvent::ARMY_SWAP ) ) {
GetArmy().SwapTroops( otherHero.GetArmy() );

armyCountBackgroundRestorerLeft.restore();
armyCountBackgroundRestorerRight.restore();

selectArmy1.ResetSelected();
selectArmy2.ResetSelected();

selectArmy1.Redraw( display );
selectArmy2.Redraw( display );

moraleIndicator1.Redraw();
moraleIndicator2.Redraw();

display.render();
}
else if ( le.MouseClickLeft( moveArtifactsToHero2.area() ) ) {
moveArtifacts( GetBagArtifacts(), otherHero.GetBagArtifacts() );

Expand Down Expand Up @@ -650,6 +679,26 @@ void Heroes::MeetingDialog( Heroes & otherHero )

display.render();
}
else if ( le.MouseClickLeft( swapAllArtifacts.area() ) ) {
BagArtifacts temp;
moveArtifacts( GetBagArtifacts(), temp );
moveArtifacts( otherHero.GetBagArtifacts(), GetBagArtifacts() );
moveArtifacts( temp, otherHero.GetBagArtifacts() );

selectArtifacts1.ResetSelected();
selectArtifacts2.ResetSelected();
selectArtifacts1.Redraw( display );
selectArtifacts2.Redraw( display );

backPrimary.restore();
fheroes2::RedrawPrimarySkillInfo( cur_pt, &primskill_bar1, &primskill_bar2 );
moraleIndicator1.Redraw();
moraleIndicator2.Redraw();
luckIndicator1.Redraw();
luckIndicator2.Redraw();

display.render();
}

if ( le.isMouseRightButtonPressedInArea( hero1Area ) ) {
Dialog::QuickInfo( *this );
Expand Down
Loading