2017-07-13 10:26:03 +02:00
/*
2023-02-01 16:42:03 +02:00
* CInfoBar . cpp , part of VCMI engine
2017-07-13 10:26:03 +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
*
*/
2012-06-13 16:04:06 +03:00
2023-02-01 20:42:06 +02:00
# include "StdInc.h"
# include "CInfoBar.h"
2014-07-15 10:14:49 +03:00
2023-05-08 14:18:34 +02:00
# include "AdventureMapInterface.h"
2014-07-13 20:53:37 +03:00
2023-02-01 20:42:06 +02:00
# include "../widgets/CComponent.h"
# include "../widgets/Images.h"
2023-03-07 02:29:04 +02:00
# include "../windows/CMessage.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/TextControls.h"
# include "../widgets/MiscWidgets.h"
2023-02-10 15:50:46 +02:00
# include "../windows/InfoWindows.h"
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
# include "../CPlayerInterface.h"
2023-04-17 01:02:31 +02:00
# include "../PlayerLocalState.h"
2014-07-13 20:53:37 +03:00
# include "../gui/CGuiHandler.h"
2023-05-16 14:10:26 +02:00
# include "../gui/WindowHandler.h"
2024-05-02 14:55:20 +02:00
# include "../media/ISoundPlayer.h"
2023-09-19 11:20:16 +02:00
# include "../render/IScreenHandler.h"
2014-07-13 20:53:37 +03:00
# include "../../CCallback.h"
2023-07-16 14:52:43 +02:00
# include "../../lib/CConfigHandler.h"
2024-07-20 14:55:17 +02:00
# include "../../lib/texts/CGeneralTextHandler.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/mapObjects/CGHeroInstance.h"
2023-02-01 20:42:06 +02:00
# include "../../lib/mapObjects/CGTownInstance.h"
2023-01-30 19:55:32 +02:00
2018-04-07 13:34:11 +02:00
CInfoBar : : CVisibleInfo : : CVisibleInfo ( )
2023-03-07 02:29:04 +02:00
: CIntObject ( 0 , Point ( offset_x , offset_y ) )
2012-06-13 16:04:06 +03:00
{
}
2023-06-02 15:42:18 +02:00
void CInfoBar : : CVisibleInfo : : show ( Canvas & to )
2012-06-13 16:04:06 +03:00
{
CIntObject : : show ( to ) ;
2013-06-29 16:05:48 +03:00
for ( auto object : forceRefresh )
2012-06-13 16:04:06 +03:00
object - > showAll ( to ) ;
}
2018-04-07 13:34:11 +02:00
CInfoBar : : EmptyVisibleInfo : : EmptyVisibleInfo ( )
2012-06-13 16:04:06 +03:00
{
}
2018-04-07 13:34:11 +02:00
CInfoBar : : VisibleHeroInfo : : VisibleHeroInfo ( const CGHeroInstance * hero )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2023-08-23 14:07:50 +02:00
background = std : : make_shared < CPicture > ( ImagePath : : builtin ( " ADSTATHR " ) ) ;
2023-07-15 23:14:59 +02:00
2023-07-16 14:52:43 +02:00
if ( settings [ " gameTweaks " ] [ " infoBarCreatureManagement " ] . Bool ( ) )
2023-07-15 23:14:59 +02:00
heroTooltip = std : : make_shared < CInteractableHeroTooltip > ( Point ( 0 , 0 ) , hero ) ;
else
heroTooltip = std : : make_shared < CHeroTooltip > ( Point ( 0 , 0 ) , hero ) ;
2012-06-13 16:04:06 +03:00
}
2018-04-07 13:34:11 +02:00
CInfoBar : : VisibleTownInfo : : VisibleTownInfo ( const CGTownInstance * town )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2023-08-23 14:07:50 +02:00
background = std : : make_shared < CPicture > ( ImagePath : : builtin ( " ADSTATCS " ) ) ;
2023-07-16 10:17:37 +02:00
2023-07-16 14:52:43 +02:00
if ( settings [ " gameTweaks " ] [ " infoBarCreatureManagement " ] . Bool ( ) )
2023-07-16 10:17:37 +02:00
townTooltip = std : : make_shared < CInteractableTownTooltip > ( Point ( 0 , 0 ) , town ) ;
else
townTooltip = std : : make_shared < CTownTooltip > ( Point ( 0 , 0 ) , town ) ;
2012-06-13 16:04:06 +03:00
}
2018-04-07 13:34:11 +02:00
CInfoBar : : VisibleDateInfo : : VisibleDateInfo ( )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2012-06-13 16:04:06 +03:00
2023-01-27 12:22:48 +02:00
animation = std : : make_shared < CShowableAnim > ( 1 , 0 , getNewDayName ( ) , CShowableAnim : : PLAY_ONCE , 180 ) ; // H3 uses around 175-180 ms per frame
2023-03-13 00:18:55 +02:00
animation - > setDuration ( 1500 ) ;
2012-06-13 16:04:06 +03:00
std : : string labelText ;
2018-04-07 13:34:11 +02:00
if ( LOCPLINT - > cb - > getDate ( Date : : DAY_OF_WEEK ) = = 1 & & LOCPLINT - > cb - > getDate ( Date : : DAY ) ! = 1 ) // monday of any week but first - show new week info
2023-03-09 15:36:46 +02:00
labelText = CGI - > generaltexth - > allTexts [ 63 ] + " " + std : : to_string ( LOCPLINT - > cb - > getDate ( Date : : WEEK ) ) ;
2012-06-13 16:04:06 +03:00
else
2023-03-09 15:36:46 +02:00
labelText = CGI - > generaltexth - > allTexts [ 64 ] + " " + std : : to_string ( LOCPLINT - > cb - > getDate ( Date : : DAY_OF_WEEK ) ) ;
2012-06-13 16:04:06 +03:00
2022-11-26 23:12:20 +02:00
label = std : : make_shared < CLabel > ( 95 , 31 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , labelText ) ;
2018-04-07 13:34:11 +02:00
forceRefresh . push_back ( label ) ;
2012-06-13 16:04:06 +03:00
}
2023-08-23 14:07:50 +02:00
AnimationPath CInfoBar : : VisibleDateInfo : : getNewDayName ( )
2012-06-13 16:04:06 +03:00
{
2018-04-07 13:34:11 +02:00
if ( LOCPLINT - > cb - > getDate ( Date : : DAY ) = = 1 )
2023-08-23 14:07:50 +02:00
return AnimationPath : : builtin ( " NEWDAY " ) ;
2012-06-13 16:04:06 +03:00
2023-03-13 00:18:55 +02:00
if ( LOCPLINT - > cb - > getDate ( Date : : DAY_OF_WEEK ) ! = 1 )
2023-09-04 13:29:02 +02:00
return AnimationPath : : builtin ( " NEWDAY " ) ;
2012-06-13 16:04:06 +03:00
2018-04-07 13:34:11 +02:00
switch ( LOCPLINT - > cb - > getDate ( Date : : WEEK ) )
{
case 1 :
2023-09-04 13:29:02 +02:00
return AnimationPath : : builtin ( " NEWWEEK1 " ) ;
2018-04-07 13:34:11 +02:00
case 2 :
2023-09-04 13:29:02 +02:00
return AnimationPath : : builtin ( " NEWWEEK2 " ) ;
2018-04-07 13:34:11 +02:00
case 3 :
2023-09-04 13:29:02 +02:00
return AnimationPath : : builtin ( " NEWWEEK3 " ) ;
2018-04-07 13:34:11 +02:00
case 4 :
2023-09-04 13:29:02 +02:00
return AnimationPath : : builtin ( " NEWWEEK4 " ) ;
2018-04-07 13:34:11 +02:00
default :
2023-08-23 14:07:50 +02:00
return AnimationPath ( ) ;
2018-04-07 13:34:11 +02:00
}
2012-06-13 16:04:06 +03:00
}
2018-04-07 13:34:11 +02:00
CInfoBar : : VisibleEnemyTurnInfo : : VisibleEnemyTurnInfo ( PlayerColor player )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2023-08-23 14:07:50 +02:00
background = std : : make_shared < CPicture > ( ImagePath : : builtin ( " ADSTATNX " ) ) ;
banner = std : : make_shared < CAnimImage > ( AnimationPath : : builtin ( " CREST58 " ) , player . getNum ( ) , 0 , 20 , 51 ) ;
sand = std : : make_shared < CShowableAnim > ( 99 , 51 , AnimationPath : : builtin ( " HOURSAND " ) , 0 , 100 ) ; // H3 uses around 100 ms per frame
glass = std : : make_shared < CShowableAnim > ( 99 , 51 , AnimationPath : : builtin ( " HOURGLAS " ) , CShowableAnim : : PLAY_ONCE , 1000 ) ; // H3 scales this nicely for AI turn duration, don't have anything like that in vcmi
2018-04-07 13:34:11 +02:00
}
2012-06-13 16:04:06 +03:00
2018-04-07 13:34:11 +02:00
CInfoBar : : VisibleGameStatusInfo : : VisibleGameStatusInfo ( )
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2012-06-13 16:04:06 +03:00
//get amount of halls of each level
std : : vector < int > halls ( 4 , 0 ) ;
2023-04-17 14:32:18 +02:00
for ( auto town : LOCPLINT - > localState - > getOwnedTowns ( ) )
2016-11-26 21:12:52 +02:00
{
int hallLevel = town - > hallLevel ( ) ;
//negative value means no village hall, unlikely but possible
if ( hallLevel > = 0 )
halls . at ( hallLevel ) + + ;
}
2012-06-13 16:04:06 +03:00
2024-01-10 00:38:54 +02:00
std : : vector < PlayerColor > allies ;
std : : vector < PlayerColor > enemies ;
2012-06-13 16:04:06 +03:00
//generate list of allies and enemies
2013-03-03 20:06:03 +03:00
for ( int i = 0 ; i < PlayerColor : : PLAYER_LIMIT_I ; i + + )
2012-06-13 16:04:06 +03:00
{
2013-12-28 21:57:08 +03:00
if ( LOCPLINT - > cb - > getPlayerStatus ( PlayerColor ( i ) , false ) = = EPlayerStatus : : INGAME )
2012-06-13 16:04:06 +03:00
{
2018-04-07 13:34:11 +02:00
if ( LOCPLINT - > cb - > getPlayerRelations ( LOCPLINT - > playerID , PlayerColor ( i ) ) ! = PlayerRelations : : ENEMIES )
2013-03-03 20:06:03 +03:00
allies . push_back ( PlayerColor ( i ) ) ;
2012-06-13 16:04:06 +03:00
else
2013-03-03 20:06:03 +03:00
enemies . push_back ( PlayerColor ( i ) ) ;
2012-06-13 16:04:06 +03:00
}
}
2018-04-07 13:34:11 +02:00
//generate widgets
2023-08-23 14:07:50 +02:00
background = std : : make_shared < CPicture > ( ImagePath : : builtin ( " ADSTATIN " ) ) ;
2022-11-26 23:12:20 +02:00
allyLabel = std : : make_shared < CLabel > ( 10 , 106 , FONT_SMALL , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 390 ] + " : " ) ;
enemyLabel = std : : make_shared < CLabel > ( 10 , 136 , FONT_SMALL , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 391 ] + " : " ) ;
2012-06-13 16:04:06 +03:00
int posx = allyLabel - > pos . w + allyLabel - > pos . x - pos . x + 4 ;
2013-06-29 16:05:48 +03:00
for ( PlayerColor & player : allies )
2012-06-13 16:04:06 +03:00
{
2023-08-23 14:07:50 +02:00
auto image = std : : make_shared < CAnimImage > ( AnimationPath : : builtin ( " ITGFLAGS " ) , player . getNum ( ) , 0 , posx , 102 ) ;
2012-06-13 16:04:06 +03:00
posx + = image - > pos . w ;
2018-04-07 13:34:11 +02:00
flags . push_back ( image ) ;
2012-06-13 16:04:06 +03:00
}
posx = enemyLabel - > pos . w + enemyLabel - > pos . x - pos . x + 4 ;
2013-06-29 16:05:48 +03:00
for ( PlayerColor & player : enemies )
2012-06-13 16:04:06 +03:00
{
2023-08-23 14:07:50 +02:00
auto image = std : : make_shared < CAnimImage > ( AnimationPath : : builtin ( " ITGFLAGS " ) , player . getNum ( ) , 0 , posx , 132 ) ;
2012-06-13 16:04:06 +03:00
posx + = image - > pos . w ;
2018-04-07 13:34:11 +02:00
flags . push_back ( image ) ;
2012-06-13 16:04:06 +03:00
}
2018-04-07 13:34:11 +02:00
for ( size_t i = 0 ; i < halls . size ( ) ; i + + )
2012-06-13 16:04:06 +03:00
{
2023-08-23 14:07:50 +02:00
hallIcons . push_back ( std : : make_shared < CAnimImage > ( AnimationPath : : builtin ( " itmtl " ) , i , 0 , 6 + 42 * ( int ) i , 11 ) ) ;
2018-04-07 13:34:11 +02:00
if ( halls [ i ] )
2023-03-09 15:36:46 +02:00
hallLabels . push_back ( std : : make_shared < CLabel > ( 26 + 42 * ( int ) i , 64 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , std : : to_string ( halls [ i ] ) ) ) ;
2012-06-13 16:04:06 +03:00
}
}
2023-03-07 02:29:04 +02:00
CInfoBar : : VisibleComponentInfo : : VisibleComponentInfo ( const std : : vector < Component > & compsToDisplay , std : : string message , int textH , bool tiny )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2012-06-13 16:04:06 +03:00
2023-08-23 14:07:50 +02:00
background = std : : make_shared < CPicture > ( ImagePath : : builtin ( " ADSTATOT " ) , 1 , 0 ) ;
2023-03-17 23:16:12 +02:00
auto fullRect = Rect ( CInfoBar : : offset , CInfoBar : : offset , data_width - 2 * CInfoBar : : offset , data_height - 2 * CInfoBar : : offset ) ;
2023-03-06 01:30:21 +02:00
auto textRect = fullRect ;
auto imageRect = fullRect ;
2023-04-08 00:44:08 +02:00
auto font = tiny ? FONT_TINY : FONT_SMALL ;
2023-03-10 17:54:37 +02:00
auto maxComponents = 2 ;
2012-06-13 16:04:06 +03:00
2023-03-06 01:30:21 +02:00
if ( ! compsToDisplay . empty ( ) )
{
auto size = CComponent : : large ;
if ( compsToDisplay . size ( ) > 2 )
2023-03-09 23:18:35 +02:00
{
2023-03-10 01:58:16 +02:00
size = CComponent : : medium ;
2023-03-09 23:18:35 +02:00
font = FONT_TINY ;
}
2023-03-07 02:29:04 +02:00
if ( ! message . empty ( ) )
2023-03-06 01:30:21 +02:00
{
2023-03-07 02:29:04 +02:00
textRect = Rect ( CInfoBar : : offset ,
CInfoBar : : offset ,
data_width - 2 * CInfoBar : : offset ,
textH ) ;
imageRect = Rect ( CInfoBar : : offset ,
2023-03-10 17:54:37 +02:00
textH ,
2023-03-07 02:29:04 +02:00
data_width - 2 * CInfoBar : : offset ,
CInfoBar : : data_height - 2 * CInfoBar : : offset - textH ) ;
2023-03-06 01:30:21 +02:00
}
2023-03-10 17:54:37 +02:00
if ( compsToDisplay . size ( ) > 4 ) {
maxComponents = 3 ;
2023-03-10 01:58:16 +02:00
size = CComponent : : small ;
2023-03-10 17:54:37 +02:00
}
if ( compsToDisplay . size ( ) > 6 )
maxComponents = 4 ;
2023-03-06 01:30:21 +02:00
std : : vector < std : : shared_ptr < CComponent > > vect ;
2012-06-13 16:04:06 +03:00
2023-03-06 01:30:21 +02:00
for ( const auto & c : compsToDisplay )
2023-03-09 23:18:35 +02:00
vect . emplace_back ( std : : make_shared < CComponent > ( c , size , font ) ) ;
2023-03-06 01:30:21 +02:00
2023-03-10 17:54:37 +02:00
comps = std : : make_shared < CComponentBox > ( vect , imageRect , 4 , 4 , 1 , maxComponents ) ;
2023-03-06 01:30:21 +02:00
}
2023-03-07 02:29:04 +02:00
if ( ! message . empty ( ) )
2023-04-07 19:50:47 +02:00
text = std : : make_shared < CMultiLineLabel > ( textRect , font , ETextAlignment : : CENTER , Colors : : WHITE , message ) ;
2023-03-07 02:29:04 +02:00
}
2018-04-07 13:34:11 +02:00
void CInfoBar : : playNewDaySound ( )
2012-06-13 16:04:06 +03:00
{
2023-09-19 09:52:32 +02:00
int volume = CCS - > soundh - > getVolume ( ) ;
int handle = - 1 ;
if ( volume = = 0 )
CCS - > soundh - > setVolume ( settings [ " general " ] [ " sound " ] . Integer ( ) ) ;
2018-04-07 13:34:11 +02:00
if ( LOCPLINT - > cb - > getDate ( Date : : DAY_OF_WEEK ) ! = 1 ) // not first day of the week
2023-09-19 09:52:32 +02:00
handle = CCS - > soundh - > playSound ( soundBase : : newDay ) ;
2018-04-07 13:34:11 +02:00
else if ( LOCPLINT - > cb - > getDate ( Date : : WEEK ) ! = 1 ) // not first week in month
2023-09-19 09:52:32 +02:00
handle = CCS - > soundh - > playSound ( soundBase : : newWeek ) ;
2018-04-07 13:34:11 +02:00
else if ( LOCPLINT - > cb - > getDate ( Date : : MONTH ) ! = 1 ) // not first month
2023-09-19 09:52:32 +02:00
handle = CCS - > soundh - > playSound ( soundBase : : newMonth ) ;
2018-04-07 13:34:11 +02:00
else
2023-09-19 09:52:32 +02:00
handle = CCS - > soundh - > playSound ( soundBase : : newDay ) ;
if ( volume = = 0 )
2023-09-19 11:20:16 +02:00
CCS - > soundh - > setCallback ( handle , [ & ] ( ) { if ( ! GH . screenHandler ( ) . hasFocus ( ) ) CCS - > soundh - > setVolume ( 0 ) ; } ) ;
2012-06-13 16:04:06 +03:00
}
2018-04-07 13:34:11 +02:00
void CInfoBar : : reset ( )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2018-04-07 13:34:11 +02:00
state = EMPTY ;
visibleInfo = std : : make_shared < EmptyVisibleInfo > ( ) ;
2012-06-13 16:04:06 +03:00
}
void CInfoBar : : showSelection ( )
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2023-04-17 12:06:58 +02:00
if ( LOCPLINT - > localState - > getCurrentHero ( ) )
2012-06-13 16:04:06 +03:00
{
2023-04-17 12:06:58 +02:00
showHeroSelection ( LOCPLINT - > localState - > getCurrentHero ( ) ) ;
2023-02-10 23:29:13 +02:00
return ;
2012-06-13 16:04:06 +03:00
}
2023-02-10 23:29:13 +02:00
2023-04-17 12:06:58 +02:00
if ( LOCPLINT - > localState - > getCurrentTown ( ) )
2023-02-10 23:29:13 +02:00
{
2023-04-17 12:06:58 +02:00
showTownSelection ( LOCPLINT - > localState - > getCurrentTown ( ) ) ;
2023-02-10 23:29:13 +02:00
return ;
}
2012-06-13 16:04:06 +03:00
showGameStatus ( ) ; //FIXME: may be incorrect but shouldn't happen in general
}
2023-03-22 23:09:43 +02:00
void CInfoBar : : tick ( uint32_t msPassed )
2012-06-13 16:04:06 +03:00
{
2023-03-22 23:09:43 +02:00
assert ( timerCounter > 0 ) ;
if ( msPassed > = timerCounter )
{
timerCounter = 0 ;
removeUsedEvents ( TIME ) ;
2023-05-16 17:34:23 +02:00
if ( GH . windows ( ) . isTopWindow ( adventureInt ) )
2023-03-22 23:09:43 +02:00
popComponents ( true ) ;
}
else
{
timerCounter - = msPassed ;
}
2012-06-13 16:04:06 +03:00
}
2023-10-10 23:51:05 +02:00
void CInfoBar : : clickReleased ( const Point & cursorPosition , bool lastActivated )
2012-06-13 16:04:06 +03:00
{
2023-07-15 23:15:59 +02:00
timerCounter = 0 ;
removeUsedEvents ( TIME ) ; //expiration trigger from just clicked element is not valid anymore
2023-07-08 13:33:04 +02:00
if ( state = = HERO | | state = = TOWN )
2023-10-10 23:51:05 +02:00
{
if ( lastActivated )
showGameStatus ( ) ;
}
2023-07-08 13:33:04 +02:00
else if ( state = = GAME )
showDate ( ) ;
else
popComponents ( true ) ;
2012-06-13 16:04:06 +03:00
}
2023-07-08 13:33:04 +02:00
void CInfoBar : : showPopupWindow ( const Point & cursorPosition )
2012-06-13 16:04:06 +03:00
{
2023-06-11 17:20:10 +02:00
CRClickPopup : : createAndPush ( CGI - > generaltexth - > allTexts [ 109 ] ) ;
2012-06-13 16:04:06 +03:00
}
void CInfoBar : : hover ( bool on )
{
2018-04-07 13:34:11 +02:00
if ( on )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( CGI - > generaltexth - > zelp [ 292 ] . first ) ;
2012-06-13 16:04:06 +03:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2012-06-13 16:04:06 +03:00
}
2018-04-07 13:34:11 +02:00
CInfoBar : : CInfoBar ( const Rect & position )
2023-06-13 18:33:35 +02:00
: CIntObject ( LCLICK | SHOW_POPUP | HOVER , position . topLeft ( ) ) ,
2023-03-22 23:09:43 +02:00
timerCounter ( 0 ) ,
2023-07-16 14:52:43 +02:00
state ( EMPTY ) ,
listener ( settings . listen [ " gameTweaks " ] [ " infoBarCreatureManagement " ] )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2012-06-13 16:04:06 +03:00
pos . w = position . w ;
pos . h = position . h ;
2023-07-16 14:52:43 +02:00
listener ( std : : bind ( & CInfoBar : : OnInfoBarCreatureManagementChanged , this ) ) ;
2018-04-07 13:34:11 +02:00
reset ( ) ;
2012-06-13 16:04:06 +03:00
}
2023-03-07 02:28:25 +02:00
CInfoBar : : CInfoBar ( const Point & position ) : CInfoBar ( Rect ( position . x , position . y , width , height ) )
{
}
2023-07-16 14:52:43 +02:00
void CInfoBar : : OnInfoBarCreatureManagementChanged ( )
{
showSelection ( ) ;
}
2023-03-22 23:09:43 +02:00
void CInfoBar : : setTimer ( uint32_t msToTrigger )
{
2023-05-17 22:22:45 +02:00
addUsedEvents ( TIME ) ;
2023-03-22 23:09:43 +02:00
timerCounter = msToTrigger ;
}
2012-06-13 16:04:06 +03:00
void CInfoBar : : showDate ( )
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2018-04-07 13:34:11 +02:00
playNewDaySound ( ) ;
state = DATE ;
visibleInfo = std : : make_shared < VisibleDateInfo > ( ) ;
2023-01-27 12:22:48 +02:00
setTimer ( 3000 ) ; // confirmed to match H3
2012-06-13 16:04:06 +03:00
redraw ( ) ;
}
2023-03-09 23:18:35 +02:00
void CInfoBar : : pushComponents ( const std : : vector < Component > & components , std : : string message , int timer )
{
2023-03-10 01:58:16 +02:00
auto actualPush = [ & ] ( const std : : vector < Component > & components , std : : string message , int timer , size_t max ) {
std : : vector < Component > vect = components ; //I do not know currently how to avoid copy here
while ( ! vect . empty ( ) )
{
std : : vector < Component > sender = { vect . begin ( ) , vect . begin ( ) + std : : min ( vect . size ( ) , max ) } ;
prepareComponents ( sender , message , timer ) ;
vect . erase ( vect . begin ( ) , vect . begin ( ) + std : : min ( vect . size ( ) , max ) ) ;
} ;
} ;
2023-03-10 20:29:20 +02:00
if ( shouldPopAll )
popAll ( ) ;
2023-03-09 23:18:35 +02:00
if ( components . empty ( ) )
prepareComponents ( components , message , timer ) ;
else
{
2023-03-10 14:54:12 +02:00
std : : array < std : : pair < std : : vector < Component > , int > , 10 > reward_map ;
2023-03-10 01:58:16 +02:00
for ( const auto & c : components )
2023-03-09 23:18:35 +02:00
{
2023-10-31 11:09:56 +02:00
switch ( c . type )
2023-03-10 14:54:12 +02:00
{
2023-10-31 11:09:56 +02:00
case ComponentType : : PRIM_SKILL :
case ComponentType : : EXPERIENCE :
case ComponentType : : LEVEL :
case ComponentType : : MANA :
2023-03-10 14:54:12 +02:00
reward_map . at ( 0 ) . first . push_back ( c ) ;
2023-03-10 17:54:37 +02:00
reward_map . at ( 0 ) . second = 8 ; //At most 8, cannot be more
2023-03-10 14:54:12 +02:00
break ;
2024-04-25 13:04:45 +02:00
case ComponentType : : NONE :
2023-10-31 11:09:56 +02:00
case ComponentType : : SEC_SKILL :
2023-03-10 14:54:12 +02:00
reward_map . at ( 1 ) . first . push_back ( c ) ;
2023-03-10 17:54:37 +02:00
reward_map . at ( 1 ) . second = 4 ; //At most 4
2023-03-10 14:54:12 +02:00
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : SPELL :
2023-03-10 14:54:12 +02:00
reward_map . at ( 2 ) . first . push_back ( c ) ;
2023-03-10 17:54:37 +02:00
reward_map . at ( 2 ) . second = 4 ; //At most 4
2023-03-10 14:54:12 +02:00
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : ARTIFACT :
case ComponentType : : SPELL_SCROLL :
2023-03-10 14:54:12 +02:00
reward_map . at ( 3 ) . first . push_back ( c ) ;
2023-03-10 17:54:37 +02:00
reward_map . at ( 3 ) . second = 4 ; //At most 4, too long names
2023-03-10 14:54:12 +02:00
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : CREATURE :
2023-03-10 14:54:12 +02:00
reward_map . at ( 4 ) . first . push_back ( c ) ;
2023-03-10 17:54:37 +02:00
reward_map . at ( 4 ) . second = 4 ; //At most 4, too long names
2023-03-10 14:54:12 +02:00
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : RESOURCE :
case ComponentType : : RESOURCE_PER_DAY :
2023-03-10 14:54:12 +02:00
reward_map . at ( 5 ) . first . push_back ( c ) ;
reward_map . at ( 5 ) . second = 7 ; //At most 7
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : MORALE :
case ComponentType : : LUCK :
2023-03-10 14:54:12 +02:00
reward_map . at ( 6 ) . first . push_back ( c ) ;
reward_map . at ( 6 ) . second = 2 ; //At most 2 - 1 for morale + 1 for luck
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : BUILDING :
2023-03-10 14:54:12 +02:00
reward_map . at ( 7 ) . first . push_back ( c ) ;
reward_map . at ( 7 ) . second = 1 ; //At most 1 - only large icons available AFAIK
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : HERO_PORTRAIT :
2023-03-10 14:54:12 +02:00
reward_map . at ( 8 ) . first . push_back ( c ) ;
reward_map . at ( 8 ) . second = 1 ; //I do not think than we even can get more than 1 hero
break ;
2023-10-31 11:09:56 +02:00
case ComponentType : : FLAG :
2023-03-10 14:54:12 +02:00
reward_map . at ( 9 ) . first . push_back ( c ) ;
reward_map . at ( 9 ) . second = 1 ; //I do not think than we even can get more than 1 player in notification
break ;
default :
logGlobal - > warn ( " Invalid component received! " ) ;
}
2023-03-09 23:18:35 +02:00
}
2023-03-10 14:54:12 +02:00
for ( const auto & kv : reward_map )
if ( ! kv . first . empty ( ) )
actualPush ( kv . first , message , timer , kv . second ) ;
2023-03-09 23:18:35 +02:00
}
popComponents ( ) ;
}
void CInfoBar : : prepareComponents ( const std : : vector < Component > & components , std : : string message , int timer )
2023-03-07 02:29:04 +02:00
{
2023-03-12 21:31:23 +02:00
auto imageH = CMessage : : getEstimatedComponentHeight ( components . size ( ) ) + ( components . empty ( ) ? 0 : 2 * CInfoBar : : offset ) ;
2023-03-07 02:29:04 +02:00
auto textH = CMessage : : guessHeight ( message , CInfoBar : : data_width - 2 * CInfoBar : : offset , FONT_SMALL ) ;
auto tinyH = CMessage : : guessHeight ( message , CInfoBar : : data_width - 2 * CInfoBar : : offset , FONT_TINY ) ;
auto header = CMessage : : guessHeader ( message ) ;
auto headerH = CMessage : : guessHeight ( header , CInfoBar : : data_width - 2 * CInfoBar : : offset , FONT_SMALL ) ;
2023-03-10 17:54:37 +02:00
auto headerTinyH = CMessage : : guessHeight ( header , CInfoBar : : data_width - 2 * CInfoBar : : offset , FONT_TINY ) ;
2023-03-07 02:29:04 +02:00
// Order matters - priority form should be chosen first
if ( imageH + textH < CInfoBar : : data_height )
2023-03-09 23:18:35 +02:00
pushComponents ( components , message , textH , false , timer ) ;
2023-03-15 13:35:34 +02:00
else if ( imageH + tinyH < CInfoBar : : data_height )
2023-03-09 23:18:35 +02:00
pushComponents ( components , message , tinyH , true , timer ) ;
2023-03-07 02:29:04 +02:00
else if ( imageH + headerH < CInfoBar : : data_height )
2023-03-09 23:18:35 +02:00
pushComponents ( components , header , headerH , false , timer ) ;
2023-03-15 13:35:34 +02:00
else if ( imageH + headerTinyH < CInfoBar : : data_height )
2023-03-10 17:54:37 +02:00
pushComponents ( components , header , headerTinyH , true , timer ) ;
2023-03-07 02:29:04 +02:00
else
2023-03-09 23:18:35 +02:00
pushComponents ( components , " " , 0 , false , timer ) ;
2023-03-07 02:29:04 +02:00
2023-03-09 23:18:35 +02:00
return ;
2023-03-07 02:29:04 +02:00
}
2023-03-10 20:29:20 +02:00
void CInfoBar : : requestPopAll ( )
{
shouldPopAll = true ;
}
2023-03-09 23:18:35 +02:00
void CInfoBar : : popAll ( )
{
componentsQueue = { } ;
2023-03-10 20:29:20 +02:00
shouldPopAll = false ;
2023-03-09 23:18:35 +02:00
}
2023-03-10 20:29:20 +02:00
void CInfoBar : : popComponents ( bool remove )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2023-03-10 20:29:20 +02:00
if ( remove & & ! componentsQueue . empty ( ) )
componentsQueue . pop ( ) ;
2023-03-09 23:18:35 +02:00
if ( ! componentsQueue . empty ( ) )
{
state = COMPONENT ;
const auto & extracted = componentsQueue . front ( ) ;
2023-03-10 01:58:16 +02:00
visibleInfo = std : : make_shared < VisibleComponentInfo > ( extracted . first ) ;
setTimer ( extracted . second ) ;
2023-03-09 23:18:35 +02:00
redraw ( ) ;
return ;
}
showSelection ( ) ;
}
2023-03-06 01:30:21 +02:00
2023-03-09 23:18:35 +02:00
void CInfoBar : : pushComponents ( const std : : vector < Component > & comps , std : : string message , int textH , bool tiny , int timer )
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2023-03-10 01:58:16 +02:00
componentsQueue . emplace ( VisibleComponentInfo : : Cache ( comps , message , textH , tiny ) , timer ) ;
2012-06-13 16:04:06 +03:00
}
2023-03-06 13:10:33 +02:00
bool CInfoBar : : showingComponents ( )
{
return state = = COMPONENT ;
}
2013-03-03 20:06:03 +03:00
void CInfoBar : : startEnemyTurn ( PlayerColor color )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2018-04-07 13:34:11 +02:00
state = AITURN ;
visibleInfo = std : : make_shared < VisibleEnemyTurnInfo > ( color ) ;
2012-06-13 16:04:06 +03:00
redraw ( ) ;
}
2012-06-22 14:40:16 +03:00
void CInfoBar : : showHeroSelection ( const CGHeroInstance * hero )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2018-04-07 13:34:11 +02:00
if ( ! hero )
{
reset ( ) ;
}
else
{
state = HERO ;
visibleInfo = std : : make_shared < VisibleHeroInfo > ( hero ) ;
}
2012-06-13 16:04:06 +03:00
redraw ( ) ;
}
2012-06-22 14:40:16 +03:00
void CInfoBar : : showTownSelection ( const CGTownInstance * town )
2012-06-13 16:04:06 +03:00
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2018-04-07 13:34:11 +02:00
if ( ! town )
{
reset ( ) ;
}
else
{
state = TOWN ;
visibleInfo = std : : make_shared < VisibleTownInfo > ( town ) ;
}
2012-06-13 16:04:06 +03:00
redraw ( ) ;
}
void CInfoBar : : showGameStatus ( )
{
2024-08-09 17:30:04 +02:00
OBJECT_CONSTRUCTION ;
2018-04-07 13:34:11 +02:00
state = GAME ;
visibleInfo = std : : make_shared < VisibleGameStatusInfo > ( ) ;
2012-06-13 16:04:06 +03:00
setTimer ( 3000 ) ;
redraw ( ) ;
}
2014-07-13 18:39:45 +03:00