Skip to content

Commit

Permalink
Change logic in monster hiring window (#2844)
Browse files Browse the repository at this point in the history
close #1744
close #838
close #1743
  • Loading branch information
ihhub authored Feb 22, 2021
1 parent cfc7d9d commit 352d84a
Show file tree
Hide file tree
Showing 5 changed files with 164 additions and 43 deletions.
41 changes: 36 additions & 5 deletions src/engine/image.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1470,7 +1470,7 @@ namespace fheroes2

if ( horizontally && !vertically ) {
const uint8_t * imageInY = in.image() + width - 1;
const uint8_t * transformInY = out.transform() + width - 1;
const uint8_t * transformInY = in.transform() + width - 1;
for ( ; imageOutY != imageOutYEnd; imageOutY += width, transformOutY += width, imageInY += width, transformInY += width ) {
uint8_t * imageOutX = imageOutY;
uint8_t * transformOutX = transformOutY;
Expand All @@ -1485,16 +1485,18 @@ namespace fheroes2
}
}
else if ( !horizontally && vertically ) {
const uint8_t * imageInY = in.image() + ( height - 1 ) * width;
const uint8_t * transformInY = out.transform() + ( height - 1 ) * width;
const int32_t offsetIn = ( height - 1 ) * width;
const uint8_t * imageInY = in.image() + offsetIn;
const uint8_t * transformInY = in.transform() + offsetIn;
for ( ; imageOutY != imageOutYEnd; imageOutY += width, transformOutY += width, imageInY -= width, transformInY -= width ) {
memcpy( imageOutY, imageInY, static_cast<size_t>( width ) );
memcpy( transformOutY, transformInY, static_cast<size_t>( width ) );
}
}
else {
const uint8_t * imageInY = in.image() + ( height - 1 ) * width + width - 1;
const uint8_t * transformInY = out.transform() + ( height - 1 ) * width + width - 1;
const int32_t offsetIn = ( height - 1 ) * width + width - 1;
const uint8_t * imageInY = in.image() + offsetIn;
const uint8_t * transformInY = in.transform() + offsetIn;
for ( ; imageOutY != imageOutYEnd; imageOutY += width, transformOutY += width, imageInY -= width, transformInY -= width ) {
uint8_t * imageOutX = imageOutY;
uint8_t * transformOutX = transformOutY;
Expand Down Expand Up @@ -1807,4 +1809,33 @@ namespace fheroes2

return out;
}

void Transpose( const Image & in, Image & out )
{
if ( in.empty() || out.empty() || in.width() != out.height() || in.height() != out.width() )
return;

const int32_t width = in.width();
const int32_t height = in.height();

const uint8_t * imageInY = in.image();
const uint8_t * imageInYEnd = imageInY + width * height;
uint8_t * imageOutX = out.image();

const uint8_t * transformInY = in.transform();
uint8_t * transformOutX = out.transform();

for ( ; imageInY != imageInYEnd; imageInY += width, transformInY += width, ++imageOutX, ++transformOutX ) {
const uint8_t * imageInX = imageInY;
const uint8_t * imageInXEnd = imageInX + width;
uint8_t * imageOutY = imageOutX;

const uint8_t * transformInX = transformInY;
uint8_t * transformOutY = transformOutX;
for ( ; imageInX != imageInXEnd; ++imageInX, ++transformInX, imageOutY += height, transformOutY += height ) {
*imageOutY = *imageInX;
*transformOutY = *transformInX;
}
}
}
}
2 changes: 2 additions & 0 deletions src/engine/image.h
Original file line number Diff line number Diff line change
Expand Up @@ -251,4 +251,6 @@ namespace fheroes2
void SetTransformPixel( Image & image, int32_t x, int32_t y, uint8_t value );

Image Stretch( const Image & in, int32_t inX, int32_t inY, int32_t widthIn, int32_t heightIn, int32_t widthOut, int32_t heightOut );

void Transpose( const Image & in, Image & out );
}
22 changes: 22 additions & 0 deletions src/fheroes2/agg/agg.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1310,6 +1310,28 @@ namespace fheroes2
modified = temp;
}
return true;
case ICN::MONSTER_SWITCH_LEFT_ARROW:
_icnVsSprite[id].resize( 2 );
for ( uint32_t i = 0; i < 2; ++i ) {
const Sprite & source = GetICN( ICN::RECRUIT, i );
Sprite & out = _icnVsSprite[id][i];
out.resize( source.height(), source.width() );
Transpose( source, out );
out = Flip( out, false, true );
out.setPosition( source.y(), source.x() );
}
return true;
case ICN::MONSTER_SWITCH_RIGHT_ARROW:
_icnVsSprite[id].resize( 2 );
for ( uint32_t i = 0; i < 2; ++i ) {
const Sprite & source = GetICN( ICN::RECRUIT, i + 2 );
Sprite & out = _icnVsSprite[id][i];
out.resize( source.height(), source.width() );
Transpose( source, out );
out = Flip( out, false, true );
out.setPosition( source.y(), source.x() );
}
return true;
default:
break;
}
Expand Down
2 changes: 2 additions & 0 deletions src/fheroes2/agg/icn.h
Original file line number Diff line number Diff line change
Expand Up @@ -916,6 +916,8 @@ namespace ICN

TROLL2MSL,
LISTBOX_EVIL, // alias to LISTBOX, but black and white colored
MONSTER_SWITCH_LEFT_ARROW,
MONSTER_SWITCH_RIGHT_ARROW,

LASTICN, // just a marker, indicating end of the enumeration
};
Expand Down
140 changes: 102 additions & 38 deletions src/fheroes2/dialog/dialog_recrut.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,8 @@
#include "text.h"
#include "world.h"

#include <cassert>

void RedrawCurrentInfo( const fheroes2::Point & pos, u32 result, const payment_t & paymentMonster, const payment_t & paymentCosts, const Funds & funds,
const std::string & label )
{
Expand Down Expand Up @@ -68,7 +70,7 @@ void RedrawResourceInfo( const fheroes2::Image & sres, const fheroes2::Point & p
text.Blit( dst_pt.x, dst_pt.y );
}

void RedrawMonsterInfo( const fheroes2::Rect & pos, const Monster & monster, u32 available, bool label, bool showTotalSum )
void RedrawMonsterInfo( const fheroes2::Rect & pos, const Monster & monster, u32 available, bool showTotalSum )
{
fheroes2::Display & display = fheroes2::Display::instance();
const payment_t paymentMonster = monster.GetCost();
Expand All @@ -93,17 +95,20 @@ void RedrawMonsterInfo( const fheroes2::Rect & pos, const Monster & monster, u32
text.Blit( dst_pt.x, dst_pt.y );

// sprite monster
const fheroes2::Sprite & smon = fheroes2::AGG::GetICN( monster.ICNMonh(), 0 );
dst_pt.x = pos.x + 27 + smon.x();
dst_pt.y = pos.y + 130 - smon.height();
fheroes2::Blit( smon, display, dst_pt.x, dst_pt.y );
const int monsterId = monster.GetID();
const Bin_Info::MonsterAnimInfo & monsterInfo = Bin_Info::GetMonsterInfo( monsterId );
assert( !monsterInfo.animationFrames[Bin_Info::MonsterAnimInfo::STATIC].empty() );

// change label
if ( label ) {
text.Set( "( change )", Font::YELLOW_SMALL );
text.Blit( pos.x + 68 - text.w() / 2, pos.y + 80 );
const fheroes2::Sprite & smon = fheroes2::AGG::GetICN( Monster::GetICNByMonsterID( monsterId ), monsterInfo.animationFrames[Bin_Info::MonsterAnimInfo::STATIC][0] );
dst_pt.x = pos.x + 80 + smon.x() - ( monster.isWide() ? 22 : 0 );
dst_pt.y = pos.y + 135 - smon.height();

if ( monsterId == Monster::CHAMPION ) {
++dst_pt.x;
}

fheroes2::Blit( smon, display, dst_pt.x, dst_pt.y );

// info resource
// gold
const fheroes2::Sprite & sgold = fheroes2::AGG::GetICN( ICN::RESOURCE, 6 );
Expand Down Expand Up @@ -172,14 +177,14 @@ void RedrawMonsterInfo( const fheroes2::Rect & pos, const Monster & monster, u32
str = _( "Available: %{count}" );
StringReplace( str, "%{count}", available );
text.Set( str, Font::SMALL );
text.Blit( pos.x + 70 - text.w() / 2, pos.y + 130 );
text.Blit( pos.x + 80 - text.w() / 2, pos.y + 135 );
}

void RedrawStaticInfo( const fheroes2::Rect & pos, const Monster & monster, u32 available, bool label )
void RedrawStaticInfo( const fheroes2::Rect & pos, const Monster & monster, u32 available )
{
fheroes2::Blit( fheroes2::AGG::GetICN( ICN::RECRBKG, 0 ), fheroes2::Display::instance(), pos.x, pos.y );

RedrawMonsterInfo( pos, monster, available, label, true );
RedrawMonsterInfo( pos, monster, available, true );

// text number buy
Text text;
Expand Down Expand Up @@ -246,8 +251,7 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext
fheroes2::Blit( boxShadow, display, pos.x - BORDERWIDTH, pos.y + BORDERWIDTH );
fheroes2::Blit( box, display, pos.x, pos.y );

const fheroes2::Rect rtChange( pos.x + 25, pos.y + 35, 85, 95 );
RedrawStaticInfo( pos, monster, available, ext && monster0.GetDowngrade() != monster0 );
RedrawStaticInfo( pos, monster, available );

// buttons
fheroes2::Point dst_pt;
Expand Down Expand Up @@ -275,6 +279,27 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext

const fheroes2::Rect rtWheel( pos.x + 130, pos.y + 155, 100, 30 );

// Create monster switching arrows
fheroes2::ButtonSprite monsterSwitchLeft;
fheroes2::ButtonSprite monsterSwitchRight;

if ( ext && monster0.GetDowngrade() != monster0 ) {
monsterSwitchLeft.setSprite( fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_LEFT_ARROW, 0 ), fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_LEFT_ARROW, 1 ) );
monsterSwitchRight.setSprite( fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_RIGHT_ARROW, 0 ), fheroes2::AGG::GetICN( ICN::MONSTER_SWITCH_RIGHT_ARROW, 1 ) );

monsterSwitchLeft.setPosition( pos.x + 24, pos.y + 80 );
monsterSwitchRight.setPosition( pos.x + 121, pos.y + 80 );
}
else {
monsterSwitchLeft.hide();
monsterSwitchRight.hide();

monsterSwitchLeft.disable();
monsterSwitchRight.disable();
}

const fheroes2::Rect monsterArea( pos.x + 40, pos.y + 35, 75, 95 );

if ( 0 == result ) {
buttonOk.disable();
buttonMax.disable();
Expand All @@ -294,12 +319,19 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext
buttonMin.draw();
buttonUp.draw();
buttonDn.draw();
monsterSwitchLeft.draw();
monsterSwitchRight.draw();

cursor.Show();
display.render();

bool redraw = false;

std::vector<Monster> upgrades = {monster0};
while ( upgrades.back().GetDowngrade() != upgrades.back() ) {
upgrades.emplace_back( upgrades.back().GetDowngrade() );
}

// str loop
while ( le.HandleEvents() ) {
if ( buttonOk.isEnabled() )
Expand All @@ -308,39 +340,67 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext
le.MousePressLeft( buttonUp.area() ) ? buttonUp.drawOnPress() : buttonUp.drawOnRelease();
le.MousePressLeft( buttonDn.area() ) ? buttonDn.drawOnPress() : buttonDn.drawOnRelease();

le.MousePressLeft( monsterSwitchLeft.area() ) ? monsterSwitchLeft.drawOnPress() : monsterSwitchLeft.drawOnRelease();
le.MousePressLeft( monsterSwitchRight.area() ) ? monsterSwitchRight.drawOnPress() : monsterSwitchRight.drawOnRelease();

if ( buttonMax.isEnabled() )
le.MousePressLeft( buttonMax.area() ) ? buttonMax.drawOnPress() : buttonMax.drawOnRelease();
if ( buttonMin.isEnabled() )
le.MousePressLeft( buttonMin.area() ) ? buttonMin.drawOnPress() : buttonMin.drawOnRelease();

if ( ext && le.MouseClickLeft( rtChange ) ) {
if ( monster != monster.GetDowngrade() ) {
monster = monster.GetDowngrade();
max = CalculateMax( monster, kingdom, available );
result = max;
paymentMonster = monster.GetCost();
paymentCosts = paymentMonster * result;
redraw = true;
bool updateCost = false;
if ( ext && upgrades.size() > 1 ) {
if ( le.MouseClickLeft( monsterSwitchLeft.area() ) || le.KeyPress( KEY_LEFT ) ) {
for ( size_t i = 0; i < upgrades.size(); ++i ) {
if ( upgrades[i] == monster ) {
if ( i < upgrades.size() - 1 ) {
monster = upgrades[i + 1];
}
else {
monster = upgrades[0];
}
break;
}
}
updateCost = true;
}
else if ( monster != monster0 ) {
monster = monster0;
max = CalculateMax( monster, kingdom, available );
result = max;
paymentMonster = monster.GetCost();
paymentCosts = paymentMonster * result;
redraw = true;
else if ( le.MouseClickLeft( monsterSwitchRight.area() ) || le.KeyPress( KEY_RIGHT ) ) {
for ( size_t i = 0; i < upgrades.size(); ++i ) {
if ( upgrades[i] == monster ) {
if ( i > 0 ) {
monster = upgrades[i - 1];
}
else {
monster = upgrades.back();
}
break;
}
}
updateCost = true;
}
}

if ( result == max ) {
maxmin = SwitchMaxMinButtons( buttonMax, buttonMin, true );
}
if ( updateCost ) {
max = CalculateMax( monster, kingdom, available );
result = max;
paymentMonster = monster.GetCost();
paymentCosts = paymentMonster * result;
redraw = true;
maxmin = SwitchMaxMinButtons( buttonMax, buttonMin, true );
}

if ( le.MousePressRight( rtChange ) ) {
bool skipEventCheck = false;
if ( le.MousePressRight( monsterArea ) ) {
const bool isUpgradedMonster = ext && ( monster != monster.GetDowngrade() );
Dialog::ArmyInfo( Troop( isUpgradedMonster ? monster : monster.GetDowngrade(), available ), Dialog::READONLY );
redraw = true;
}
else if ( le.MouseClickLeft( monsterArea ) ) {
const bool isUpgradedMonster = ext && ( monster != monster.GetDowngrade() );
Dialog::ArmyInfo( Troop( isUpgradedMonster ? monster : monster.GetDowngrade(), available ), Dialog::READONLY | Dialog::BUTTONS );
redraw = true;
skipEventCheck = true;
}

if ( PressIntKey( max, result ) ) {
paymentCosts = paymentMonster * result;
Expand All @@ -355,7 +415,7 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext
}
}

if ( ( le.MouseWheelUp( rtWheel ) || le.MouseClickLeft( buttonUp.area() ) ) && result < max ) {
if ( ( le.MouseWheelUp( rtWheel ) || le.MouseClickLeft( buttonUp.area() ) || le.KeyPress( KEY_UP ) ) && result < max ) {
++result;
paymentCosts += paymentMonster;
redraw = true;
Expand All @@ -368,7 +428,7 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext
maxmin = SwitchMaxMinButtons( buttonMax, buttonMin, false );
}
}
else if ( ( le.MouseWheelDn( rtWheel ) || le.MouseClickLeft( buttonDn.area() ) ) && result ) {
else if ( ( le.MouseWheelDn( rtWheel ) || le.MouseClickLeft( buttonDn.area() ) || le.KeyPress( KEY_DOWN ) ) && result ) {
--result;
paymentCosts -= paymentMonster;
redraw = true;
Expand Down Expand Up @@ -396,7 +456,7 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext

if ( redraw ) {
cursor.Hide();
RedrawStaticInfo( pos, monster, available, ext && monster0.GetDowngrade() != monster0 );
RedrawStaticInfo( pos, monster, available );
RedrawCurrentInfo( fheroes2::Point( pos.x, pos.y ), result, paymentMonster, paymentCosts, funds, maxmin );

if ( 0 == result ) {
Expand All @@ -412,6 +472,10 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext
buttonMax.draw();
if ( buttonMin.isEnabled() )
buttonMin.draw();

monsterSwitchLeft.draw();
monsterSwitchRight.draw();

cursor.Show();
display.render();
redraw = false;
Expand All @@ -420,7 +484,7 @@ Troop Dialog::RecruitMonster( const Monster & monster0, u32 available, bool ext
if ( buttonOk.isEnabled() && ( le.MouseClickLeft( buttonOk.area() ) || Game::HotKeyPressEvent( Game::EVENT_DEFAULT_READY ) ) )
break;

if ( le.MouseClickLeft( buttonCancel.area() ) || Game::HotKeyPressEvent( Game::EVENT_DEFAULT_EXIT ) ) {
if ( le.MouseClickLeft( buttonCancel.area() ) || ( Game::HotKeyPressEvent( Game::EVENT_DEFAULT_EXIT ) && !skipEventCheck ) ) {
result = 0;
break;
}
Expand Down Expand Up @@ -461,7 +525,7 @@ void Dialog::DwellingInfo( const Monster & monster, u32 available )

LocalEvent & le = LocalEvent::Get();

RedrawMonsterInfo( pos, monster, available, false, false );
RedrawMonsterInfo( pos, monster, available, false );

cursor.Show();
display.render();
Expand Down

0 comments on commit 352d84a

Please sign in to comment.