From a9f89a0618e2d3411b28d9a155f8e0e7f3f36523 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 8 Dec 2024 15:50:12 +0100 Subject: [PATCH 01/19] Move single arrows --- src/fheroes2/heroes/heroes_meeting.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index c43e3c2ad7c..6232d84c8e2 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -346,8 +346,8 @@ 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 + 317, display ); + fheroes2::ButtonSprite moveArmyToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 472, cur_pt.y + 317, 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 ); @@ -393,8 +393,8 @@ 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 + 423, display ); + fheroes2::ButtonSprite moveArtifactsToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 472, cur_pt.y + 423, display ); // button exit dst_pt.x = cur_pt.x + 280; From 8ab3108bc5624646b8bc92793fb4acd71808680b Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 8 Dec 2024 20:24:57 +0100 Subject: [PATCH 02/19] Adjust arrow placements and restorers --- src/fheroes2/heroes/heroes_meeting.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index 6232d84c8e2..cefea317f54 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -346,11 +346,11 @@ 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 + 126, cur_pt.y + 317, display ); - fheroes2::ButtonSprite moveArmyToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 472, cur_pt.y + 317, 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::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; @@ -393,8 +393,8 @@ 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 + 126, cur_pt.y + 423, display ); - fheroes2::ButtonSprite moveArtifactsToHero1 = createMoveButton( ICN::SWAP_ARROW_RIGHT_TO_LEFT, cur_pt.x + 472, cur_pt.y + 423, 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 ); // button exit dst_pt.x = cur_pt.x + 280; From be1029942594ed6653bb2a34758c62baa2ee0e33 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sat, 28 Dec 2024 02:30:35 +0100 Subject: [PATCH 03/19] Generate swap circular arrows First draft --- src/fheroes2/agg/agg_image.cpp | 123 +++++++++++++++++++++++++++++++++ src/fheroes2/agg/icn.h | 3 +- 2 files changed, 125 insertions(+), 1 deletion(-) diff --git a/src/fheroes2/agg/agg_image.cpp b/src/fheroes2/agg/agg_image.cpp index 04ca18ba258..b1cacba5175 100644 --- a/src/fheroes2/agg/agg_image.cpp +++ b/src/fheroes2/agg/agg_image.cpp @@ -3232,6 +3232,129 @@ 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 unRotated; + unRotated.resize( arrowTipToShaftLength, arrowHeadWidth ); + unRotated.reset(); + Copy( original, original.width() - arrowTipToShaftLength, 0, unRotated, 0, 0, arrowTipToShaftLength, arrowHeadWidth ); + fheroes2::Image rotated; + rotated.resize( arrowHeadWidth, arrowTipToShaftLength ); + rotated.reset(); + for ( int x = 0; x < arrowTipToShaftLength; ++x ) { + for ( int y = 0; y < arrowHeadWidth; ++y ) { + Copy( unRotated, x, y, rotated, arrowHeadWidth - y - 1, arrowTipToShaftLength - x - 1, 1, 1 ); + } + } + + // Rotate arrow ends + const int32_t arrowEndHeight = 11; + const int32_t arrowEndWidth = 9; + + fheroes2::Image endRotated; + endRotated.resize( arrowEndWidth, arrowEndHeight ); + + for ( int x = 0; x < arrowEndHeight; ++x ) { + for ( int y = 0; y < arrowEndWidth; ++y ) { + Copy( original, x + 2, y + 5, endRotated, arrowEndWidth - y - 1, arrowEndHeight - x - 1, 1, 1 ); + } + } + // Remove black corner. + fheroes2::Copy( original, 0, 0, endRotated, 0, endRotated.height() - 1, 1, 1 ); + + fheroes2::Copy( endRotated, 0, 0, out, 32, 6, arrowEndWidth, arrowEndHeight ); + fheroes2::Copy( Flip( endRotated, false, true ), 0, 0, out, 5, 25, arrowEndWidth, arrowEndHeight ); + + fheroes2::Copy( Flip( rotated, true, true ), 0, 0, out, 0, 5, arrowHeadWidth, arrowTipToShaftLength ); + fheroes2::Copy( Flip( rotated, true, false ), 0, 0, out, 27, 19, arrowHeadWidth, arrowTipToShaftLength ); + + // 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 ); + + // Add corners. + // 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( endRotated, 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 ) { diff --git a/src/fheroes2/agg/icn.h b/src/fheroes2/agg/icn.h index a32cc6ff04c..81ca9c717bc 100644 --- a/src/fheroes2/agg/icn.h +++ b/src/fheroes2/agg/icn.h @@ -941,9 +941,10 @@ namespace ICN WHITE_LARGE_FONT, GOLDEN_GRADIENT_LARGE_FONT, - SILVER_GRADIENT_LARGE_FONT, SWAP_ARROW_LEFT_TO_RIGHT, + SILVER_GRADIENT_LARGE_FONT, SWAP_ARROW_RIGHT_TO_LEFT, + SWAP_ARROWS_CIRCULAR, COLOR_CURSOR_ADVENTURE_MAP, MONO_CURSOR_ADVENTURE_MAP, From 7950ab1cca1e1a0fa527b68307c502b1082f5f68 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sat, 28 Dec 2024 02:37:01 +0100 Subject: [PATCH 04/19] Revert ICN move --- src/fheroes2/agg/icn.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fheroes2/agg/icn.h b/src/fheroes2/agg/icn.h index 81ca9c717bc..b6356852afe 100644 --- a/src/fheroes2/agg/icn.h +++ b/src/fheroes2/agg/icn.h @@ -941,8 +941,8 @@ namespace ICN WHITE_LARGE_FONT, GOLDEN_GRADIENT_LARGE_FONT, - SWAP_ARROW_LEFT_TO_RIGHT, SILVER_GRADIENT_LARGE_FONT, + SWAP_ARROW_LEFT_TO_RIGHT, SWAP_ARROW_RIGHT_TO_LEFT, SWAP_ARROWS_CIRCULAR, From 9db4404a2a9ffb02d0158e18d8651cc7308432a2 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sat, 28 Dec 2024 15:52:03 +0100 Subject: [PATCH 05/19] Arrow generation Tidying --- src/fheroes2/agg/agg_image.cpp | 42 +++++++++++++++------------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/src/fheroes2/agg/agg_image.cpp b/src/fheroes2/agg/agg_image.cpp index b1cacba5175..0de70603f56 100644 --- a/src/fheroes2/agg/agg_image.cpp +++ b/src/fheroes2/agg/agg_image.cpp @@ -3245,52 +3245,48 @@ namespace const int32_t arrowTipToShaftLength = 18; const int32_t arrowHeadWidth = 20; - fheroes2::Image unRotated; - unRotated.resize( arrowTipToShaftLength, arrowHeadWidth ); - unRotated.reset(); - Copy( original, original.width() - arrowTipToShaftLength, 0, unRotated, 0, 0, arrowTipToShaftLength, arrowHeadWidth ); - fheroes2::Image rotated; - rotated.resize( arrowHeadWidth, arrowTipToShaftLength ); - rotated.reset(); + fheroes2::Image rotatedArrow; + rotatedArrow.resize( arrowHeadWidth, arrowTipToShaftLength ); + rotatedArrow.reset(); for ( int x = 0; x < arrowTipToShaftLength; ++x ) { for ( int y = 0; y < arrowHeadWidth; ++y ) { - Copy( unRotated, x, y, rotated, arrowHeadWidth - y - 1, arrowTipToShaftLength - x - 1, 1, 1 ); + 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 + // Rotate arrow ends. const int32_t arrowEndHeight = 11; const int32_t arrowEndWidth = 9; - fheroes2::Image endRotated; - endRotated.resize( arrowEndWidth, arrowEndHeight ); + 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, endRotated, arrowEndWidth - y - 1, arrowEndHeight - x - 1, 1, 1 ); + Copy( original, x + 2, y + 5, rotatedArrow, arrowEndWidth - y - 1, arrowEndHeight - x - 1, 1, 1 ); } } - // Remove black corner. - fheroes2::Copy( original, 0, 0, endRotated, 0, endRotated.height() - 1, 1, 1 ); - fheroes2::Copy( endRotated, 0, 0, out, 32, 6, arrowEndWidth, arrowEndHeight ); - fheroes2::Copy( Flip( endRotated, false, true ), 0, 0, out, 5, 25, arrowEndWidth, arrowEndHeight ); + // Clean black corner. + fheroes2::Copy( original, 0, 0, rotatedArrow, 0, rotatedArrow.height() - 1, 1, 1 ); - fheroes2::Copy( Flip( rotated, true, true ), 0, 0, out, 0, 5, arrowHeadWidth, arrowTipToShaftLength ); - fheroes2::Copy( Flip( rotated, true, false ), 0, 0, out, 27, 19, arrowHeadWidth, arrowTipToShaftLength ); + 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 + // 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 + // 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 ); - // Add corners. // 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 ); @@ -3302,7 +3298,7 @@ namespace // Lower left corner. Copy( original, 5, 9, out, 9, out.height() - 6, 3, 6 ); - Copy( endRotated, 0, 0, out, 5, out.height() - 7, 4, 2 ); + 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 ); From 74b550a53d5b23ab28caf80a21999b6973515f92 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sat, 28 Dec 2024 23:37:36 +0100 Subject: [PATCH 06/19] Code style --- src/fheroes2/agg/agg_image.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/fheroes2/agg/agg_image.cpp b/src/fheroes2/agg/agg_image.cpp index 0de70603f56..2a1b64fed6d 100644 --- a/src/fheroes2/agg/agg_image.cpp +++ b/src/fheroes2/agg/agg_image.cpp @@ -3253,7 +3253,7 @@ namespace 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 ); From 9867f3ffdb85235956629d4c580b1004789900e9 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 01:27:40 +0100 Subject: [PATCH 07/19] Implement swap function --- src/fheroes2/army/army.cpp | 9 +++++++++ src/fheroes2/army/army.h | 4 +++- 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/fheroes2/army/army.cpp b/src/fheroes2/army/army.cpp index aaca58f727c..da5e22f9112 100644 --- a/src/fheroes2/army/army.cpp +++ b/src/fheroes2/army/army.cpp @@ -1509,6 +1509,15 @@ void Army::MoveTroops( Army & from, const int monsterIdToKeep ) moveTroops( false ); } +void Army::SwapTroops( Army & from ) +{ + assert( this != &from ); + const Troops temp = this->getTroops(); + this->Reset(); + Assign( from ); + from.Assign( temp ); +} + uint32_t Army::ActionToSirens() const { uint32_t experience = 0; diff --git a/src/fheroes2/army/army.h b/src/fheroes2/army/army.h index 868c5ba920f..349888d04c5 100644 --- a/src/fheroes2/army/army.h +++ b/src/fheroes2/army/army.h @@ -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 ) { From 504ed2754b20c19fd6924f9451d00c56a858591a Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 01:38:22 +0100 Subject: [PATCH 08/19] Add swap armies button to heroes meeting --- src/fheroes2/game/game_hotkeys.cpp | 2 ++ src/fheroes2/game/game_hotkeys.h | 1 + src/fheroes2/heroes/heroes_meeting.cpp | 28 +++++++++++++++++++++++--- 3 files changed, 28 insertions(+), 3 deletions(-) diff --git a/src/fheroes2/game/game_hotkeys.cpp b/src/fheroes2/game/game_hotkeys.cpp index 27af9193e54..be067217449 100644 --- a/src/fheroes2/game/game_hotkeys.cpp +++ b/src/fheroes2/game/game_hotkeys.cpp @@ -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() diff --git a/src/fheroes2/game/game_hotkeys.h b/src/fheroes2/game/game_hotkeys.h index a128eb90fca..d0c58d702d8 100644 --- a/src/fheroes2/game/game_hotkeys.h +++ b/src/fheroes2/game/game_hotkeys.h @@ -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, diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index cefea317f54..247a5096e29 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -348,6 +348,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) // 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 + 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 + 311, 223, 8 ); fheroes2::ImageRestorer armyCountBackgroundRestorerRight( display, cur_pt.x + 381, cur_pt.y + 311, 223, 8 ); @@ -403,6 +404,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) moveArmyToHero2.draw(); moveArmyToHero1.draw(); + swapArmies.draw(); moveArtifactsToHero2.draw(); moveArtifactsToHero1.draw(); buttonExit.draw(); @@ -420,17 +422,25 @@ void Heroes::MeetingDialog( Heroes & otherHero ) while ( le.HandleEvents() ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); - if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero2.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) ) { + if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero2.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) ) + { moveArmyToHero2.drawOnPress(); moveArmyToHero1.drawOnRelease(); } - else if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero1.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_LEFT ) ) { + else if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero1.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_LEFT ) ) + { moveArmyToHero1.drawOnPress(); moveArmyToHero2.drawOnRelease(); } - else { + 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() ) ) { @@ -616,6 +626,18 @@ 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() ); From a2b2adb39e6eb22bc3dcf3d428dcf6e994129475 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 01:38:43 +0100 Subject: [PATCH 09/19] code style --- src/fheroes2/heroes/heroes_meeting.cpp | 12 ++++-------- 1 file changed, 4 insertions(+), 8 deletions(-) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index 247a5096e29..1f053b4f79d 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -422,22 +422,18 @@ void Heroes::MeetingDialog( Heroes & otherHero ) while ( le.HandleEvents() ) { buttonExit.drawOnState( le.isMouseLeftButtonPressedInArea( buttonExit.area() ) ); - if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero2.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) ) - { + if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero2.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_RIGHT ) ) { moveArmyToHero2.drawOnPress(); moveArmyToHero1.drawOnRelease(); } - else if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero1.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_LEFT ) ) - { + else if ( le.isMouseLeftButtonPressedInArea( moveArmyToHero1.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::DEFAULT_LEFT ) ) { moveArmyToHero1.drawOnPress(); moveArmyToHero2.drawOnRelease(); } - else if ( le.isMouseLeftButtonPressedInArea( swapArmies.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SWAP ) ) - { + else if ( le.isMouseLeftButtonPressedInArea( swapArmies.area() ) || HotKeyHoldEvent( Game::HotKeyEvent::ARMY_SWAP ) ) { swapArmies.drawOnPress(); } - else - { + else { moveArmyToHero1.drawOnRelease(); moveArmyToHero2.drawOnRelease(); swapArmies.drawOnRelease(); From a14977b83c5b1b54a308d9b82d1fe5a0e55a2f97 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 01:39:31 +0100 Subject: [PATCH 10/19] white spaces --- src/fheroes2/heroes/heroes_meeting.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index 1f053b4f79d..63373023ee7 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -624,14 +624,19 @@ void Heroes::MeetingDialog( Heroes & otherHero ) } 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() ) ) { From ee6c61ae12fa6c292e991ce89f8bed7b09ab4988 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 01:59:25 +0100 Subject: [PATCH 11/19] Add swap artifacts --- src/fheroes2/heroes/heroes_meeting.cpp | 22 ++++++++++++++++++++++ 1 file changed, 22 insertions(+) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index 63373023ee7..ba2e754aa3f 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -396,6 +396,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) 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 + 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 swapArtifacts = createMoveButton( ICN::SWAP_ARROWS_CIRCULAR, cur_pt.x + 297, cur_pt.y + 361, display ); // button exit dst_pt.x = cur_pt.x + 280; @@ -407,6 +408,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) swapArmies.draw(); moveArtifactsToHero2.draw(); moveArtifactsToHero1.draw(); + swapArtifacts.draw(); buttonExit.draw(); // Fade-in heroes meeting dialog. Use half fade if game resolution is not 640x480. @@ -447,9 +449,13 @@ void Heroes::MeetingDialog( Heroes & otherHero ) moveArtifactsToHero1.drawOnPress(); moveArtifactsToHero2.drawOnRelease(); } + else if ( le.isMouseLeftButtonPressedInArea( swapArtifacts.area() ) ) { + swapArtifacts.drawOnPress(); + } else { moveArtifactsToHero1.drawOnRelease(); moveArtifactsToHero2.drawOnRelease(); + swapArtifacts.drawOnRelease(); } if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) @@ -673,6 +679,22 @@ void Heroes::MeetingDialog( Heroes & otherHero ) display.render(); } + else if ( le.MouseClickLeft( swapArtifacts.area() ) ) { + std::swap( GetBagArtifacts(), 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 ); From 9684b7381009d0da72531cc72e5d8dea6bee9938 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 02:54:14 +0100 Subject: [PATCH 12/19] Remove artifact swapping --- src/fheroes2/heroes/heroes_meeting.cpp | 26 ++------------------------ 1 file changed, 2 insertions(+), 24 deletions(-) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index ba2e754aa3f..46844561525 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -394,9 +394,8 @@ 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 + 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 swapArtifacts = createMoveButton( ICN::SWAP_ARROWS_CIRCULAR, cur_pt.x + 297, cur_pt.y + 361, display ); + 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 ); // button exit dst_pt.x = cur_pt.x + 280; @@ -408,7 +407,6 @@ void Heroes::MeetingDialog( Heroes & otherHero ) swapArmies.draw(); moveArtifactsToHero2.draw(); moveArtifactsToHero1.draw(); - swapArtifacts.draw(); buttonExit.draw(); // Fade-in heroes meeting dialog. Use half fade if game resolution is not 640x480. @@ -449,13 +447,9 @@ void Heroes::MeetingDialog( Heroes & otherHero ) moveArtifactsToHero1.drawOnPress(); moveArtifactsToHero2.drawOnRelease(); } - else if ( le.isMouseLeftButtonPressedInArea( swapArtifacts.area() ) ) { - swapArtifacts.drawOnPress(); - } else { moveArtifactsToHero1.drawOnRelease(); moveArtifactsToHero2.drawOnRelease(); - swapArtifacts.drawOnRelease(); } if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) @@ -679,22 +673,6 @@ void Heroes::MeetingDialog( Heroes & otherHero ) display.render(); } - else if ( le.MouseClickLeft( swapArtifacts.area() ) ) { - std::swap( GetBagArtifacts(), 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 ); From 33a0e6b9a757c31ccfd1c7c760d21da06edbd02f Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 03:21:02 +0100 Subject: [PATCH 13/19] Implement swap artifacts --- src/fheroes2/heroes/heroes_meeting.cpp | 27 ++++++++++++++++++++++++-- 1 file changed, 25 insertions(+), 2 deletions(-) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index 46844561525..ea1ce7ad0c3 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -394,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; @@ -407,6 +408,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) swapArmies.draw(); moveArtifactsToHero2.draw(); moveArtifactsToHero1.draw(); + swapAllArtifacts.draw(); buttonExit.draw(); // Fade-in heroes meeting dialog. Use half fade if game resolution is not 640x480. @@ -450,6 +452,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) else { moveArtifactsToHero1.drawOnRelease(); moveArtifactsToHero2.drawOnRelease(); + swapAllArtifacts.drawOnRelease(); } if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) @@ -673,6 +676,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 ); From acd28886a5ccedf4441d8c0049fe438eee937fb2 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 10:32:21 +0100 Subject: [PATCH 14/19] Remove reset army call --- src/fheroes2/army/army.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/fheroes2/army/army.cpp b/src/fheroes2/army/army.cpp index da5e22f9112..73335c11d9d 100644 --- a/src/fheroes2/army/army.cpp +++ b/src/fheroes2/army/army.cpp @@ -1513,7 +1513,6 @@ void Army::SwapTroops( Army & from ) { assert( this != &from ); const Troops temp = this->getTroops(); - this->Reset(); Assign( from ); from.Assign( temp ); } From 87c6bbc5130c271658bd2f1c61d54b8a3c36c7b6 Mon Sep 17 00:00:00 2001 From: Zenseii Date: Sun, 29 Dec 2024 10:33:50 +0100 Subject: [PATCH 15/19] Pressed state for artifacts --- src/fheroes2/heroes/heroes_meeting.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index ea1ce7ad0c3..e3b71a4d532 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -449,6 +449,9 @@ void Heroes::MeetingDialog( Heroes & otherHero ) moveArtifactsToHero1.drawOnPress(); moveArtifactsToHero2.drawOnRelease(); } + else if ( le.isMouseLeftButtonPressedInArea( swapAllArtifacts.area() ) ) { + swapAllArtifacts.drawOnPress(); + } else { moveArtifactsToHero1.drawOnRelease(); moveArtifactsToHero2.drawOnRelease(); From ce73e959f075d18f03359a92af06e0ef0666a9f7 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Sun, 29 Dec 2024 17:23:45 +0300 Subject: [PATCH 16/19] Add an assertion and document it --- src/fheroes2/army/army.cpp | 6 ++++++ src/fheroes2/army/army.h | 4 +++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/fheroes2/army/army.cpp b/src/fheroes2/army/army.cpp index 73335c11d9d..1f7626faf33 100644 --- a/src/fheroes2/army/army.cpp +++ b/src/fheroes2/army/army.cpp @@ -1512,7 +1512,13 @@ void Army::MoveTroops( Army & from, const int monsterIdToKeep ) void Army::SwapTroops( Army & from ) { assert( this != &from ); + + // Heroes need to have at least one occupied slot in their army, so both armies should have at least one + // occupied slot, even if the exchange of armies takes place between a castle garrison and a hero. + assert( from.isValid() && isValid() ); + const Troops temp = this->getTroops(); + Assign( from ); from.Assign( temp ); } diff --git a/src/fheroes2/army/army.h b/src/fheroes2/army/army.h index 349888d04c5..07acccb2da9 100644 --- a/src/fheroes2/army/army.h +++ b/src/fheroes2/army/army.h @@ -230,7 +230,9 @@ class Army final : public Troops, public Control // 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 + // 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 - provided that there is at least one occupied slot in the castle garrison. It's the caller's responsibility + // to ensure that this is indeed the case. void SwapTroops( Army & from ); void SetSpreadFormation( const bool spread ) From 2f753035e487c778fa92c3de85568c40a27c6c59 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Sun, 29 Dec 2024 17:19:15 +0300 Subject: [PATCH 17/19] swapAllArtifacts -> swapArtifacts --- src/fheroes2/heroes/heroes_meeting.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/src/fheroes2/heroes/heroes_meeting.cpp b/src/fheroes2/heroes/heroes_meeting.cpp index e3b71a4d532..d5f36f7a621 100644 --- a/src/fheroes2/heroes/heroes_meeting.cpp +++ b/src/fheroes2/heroes/heroes_meeting.cpp @@ -396,7 +396,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) 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 + 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 ); + fheroes2::ButtonSprite swapArtifacts = createMoveButton( ICN::SWAP_ARROWS_CIRCULAR, cur_pt.x + 297, cur_pt.y + 361, display ); // button exit dst_pt.x = cur_pt.x + 280; @@ -408,7 +408,7 @@ void Heroes::MeetingDialog( Heroes & otherHero ) swapArmies.draw(); moveArtifactsToHero2.draw(); moveArtifactsToHero1.draw(); - swapAllArtifacts.draw(); + swapArtifacts.draw(); buttonExit.draw(); // Fade-in heroes meeting dialog. Use half fade if game resolution is not 640x480. @@ -449,13 +449,13 @@ void Heroes::MeetingDialog( Heroes & otherHero ) moveArtifactsToHero1.drawOnPress(); moveArtifactsToHero2.drawOnRelease(); } - else if ( le.isMouseLeftButtonPressedInArea( swapAllArtifacts.area() ) ) { - swapAllArtifacts.drawOnPress(); + else if ( le.isMouseLeftButtonPressedInArea( swapArtifacts.area() ) ) { + swapArtifacts.drawOnPress(); } else { moveArtifactsToHero1.drawOnRelease(); moveArtifactsToHero2.drawOnRelease(); - swapAllArtifacts.drawOnRelease(); + swapArtifacts.drawOnRelease(); } if ( le.MouseClickLeft( buttonExit.area() ) || Game::HotKeyCloseWindow() ) @@ -679,21 +679,26 @@ void Heroes::MeetingDialog( Heroes & otherHero ) display.render(); } - else if ( le.MouseClickLeft( swapAllArtifacts.area() ) ) { + else if ( le.MouseClickLeft( swapArtifacts.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(); From 9cddaa7483c2f77cae4edf17aa251830dacd4230 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Sun, 29 Dec 2024 17:33:07 +0300 Subject: [PATCH 18/19] Style nits --- src/fheroes2/army/army.cpp | 7 +++++-- src/fheroes2/army/army.h | 4 ++-- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/src/fheroes2/army/army.cpp b/src/fheroes2/army/army.cpp index 1f7626faf33..e56af8d3a3b 100644 --- a/src/fheroes2/army/army.cpp +++ b/src/fheroes2/army/army.cpp @@ -261,8 +261,10 @@ void Troops::Assign( const Troops & troops ) const_iterator it2 = troops.begin(); while ( it1 != end() && it2 != troops.end() ) { - if ( ( *it2 )->isValid() ) + if ( ( *it2 )->isValid() ) { ( *it1 )->Set( **it2 ); + } + ++it2; ++it1; } @@ -270,8 +272,9 @@ void Troops::Assign( const Troops & troops ) void Troops::Insert( const Troops & troops ) { - for ( const_iterator it = troops.begin(); it != troops.end(); ++it ) + for ( const_iterator it = troops.begin(); it != troops.end(); ++it ) { push_back( new Troop( **it ) ); + } } void Troops::PushBack( const Monster & mons, uint32_t count ) diff --git a/src/fheroes2/army/army.h b/src/fheroes2/army/army.h index 07acccb2da9..f0d74f305fb 100644 --- a/src/fheroes2/army/army.h +++ b/src/fheroes2/army/army.h @@ -58,8 +58,8 @@ class Troops : protected std::vector Troops & operator=( const Troops & ) = delete; void Assign( const Troop * itbeg, const Troop * itend ); - void Assign( const Troops & ); - void Insert( const Troops & ); + void Assign( const Troops & troops ); + void Insert( const Troops & troops ); void PushBack( const Monster &, uint32_t ); void PopBack(); From 0ea65b35db17beeb7570a6bdfd6810fac969c384 Mon Sep 17 00:00:00 2001 From: Oleg Derevenetz Date: Sun, 29 Dec 2024 17:55:24 +0300 Subject: [PATCH 19/19] Modernize the code a bit --- src/fheroes2/army/army.cpp | 33 ++++++++++++++------------------- src/fheroes2/army/army.h | 4 ++-- 2 files changed, 16 insertions(+), 21 deletions(-) diff --git a/src/fheroes2/army/army.cpp b/src/fheroes2/army/army.cpp index e56af8d3a3b..479016311d1 100644 --- a/src/fheroes2/army/army.cpp +++ b/src/fheroes2/army/army.cpp @@ -237,19 +237,16 @@ Troops::~Troops() } ); } -void Troops::Assign( const Troop * itbeg, const Troop * itend ) +void Troops::Assign( const Troop * troopsBegin, const Troop * troopsEnd ) { Clean(); - iterator it = begin(); + for ( iterator iter = begin(); iter != end() && troopsBegin != troopsEnd; ++iter, ++troopsBegin ) { + assert( *iter != nullptr && troopsBegin != nullptr ); - while ( it != end() && itbeg != itend ) { - if ( itbeg->isValid() ) { - ( *it )->Set( *itbeg ); + if ( troopsBegin->isValid() ) { + ( *iter )->Set( *troopsBegin ); } - - ++it; - ++itbeg; } } @@ -257,27 +254,25 @@ void Troops::Assign( const Troops & troops ) { Clean(); - iterator it1 = begin(); - const_iterator it2 = troops.begin(); + for ( auto [thisIter, troopsIter] = std::make_pair( begin(), troops.begin() ); thisIter != end() && troopsIter != troops.end(); ++thisIter, ++troopsIter ) { + assert( *thisIter != nullptr && *troopsIter != nullptr ); - while ( it1 != end() && it2 != troops.end() ) { - if ( ( *it2 )->isValid() ) { - ( *it1 )->Set( **it2 ); + if ( ( *troopsIter )->isValid() ) { + ( *thisIter )->Set( **troopsIter ); } - - ++it2; - ++it1; } } void Troops::Insert( const Troops & troops ) { - for ( const_iterator it = troops.begin(); it != troops.end(); ++it ) { - push_back( new Troop( **it ) ); + for ( const Troop * troop : troops ) { + assert( troop != nullptr ); + + push_back( new Troop( *troop ) ); } } -void Troops::PushBack( const Monster & mons, uint32_t count ) +void Troops::PushBack( const Monster & mons, const uint32_t count ) { push_back( new Troop( mons, count ) ); } diff --git a/src/fheroes2/army/army.h b/src/fheroes2/army/army.h index f0d74f305fb..4fb36b03e3f 100644 --- a/src/fheroes2/army/army.h +++ b/src/fheroes2/army/army.h @@ -57,10 +57,10 @@ class Troops : protected std::vector Troops & operator=( const Troops & ) = delete; - void Assign( const Troop * itbeg, const Troop * itend ); + void Assign( const Troop * troopsBegin, const Troop * troopsEnd ); void Assign( const Troops & troops ); void Insert( const Troops & troops ); - void PushBack( const Monster &, uint32_t ); + void PushBack( const Monster & mons, const uint32_t count ); void PopBack(); size_t Size() const