2017-07-13 11:26:03 +03:00
/*
2023-02-01 16:42:03 +02:00
* CInfoBar.cpp, part of VCMI engine
2017-07-13 11:26:03 +03: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
*
*/
2023-02-01 20:42:06 +02:00
2012-06-13 13:04:06 +00:00
#include "StdInc.h"
2023-02-01 20:42:06 +02:00
#include "CInfoBar.h"
2012-06-13 13:04:06 +00:00
2023-02-01 20:42:06 +02:00
#include "CAdvMapInt.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"
#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 "../CMusicHandler.h"
#include "../CPlayerInterface.h"
#include "../gui/CGuiHandler.h"
#include "../../CCallback.h"
#include "../../lib/CGeneralTextHandler.h"
#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 14:34:11 +03:00
CInfoBar :: CVisibleInfo :: CVisibleInfo ()
: CIntObject ( 0 , Point ( 8 , 12 ))
2012-06-13 13:04:06 +00:00
{
}
2018-04-07 14:34:11 +03:00
void CInfoBar :: CVisibleInfo :: show ( SDL_Surface * to )
2012-06-13 13:04:06 +00:00
{
CIntObject :: show ( to );
2013-06-29 13:05:48 +00:00
for ( auto object : forceRefresh )
2012-06-13 13:04:06 +00:00
object -> showAll ( to );
}
2018-04-07 14:34:11 +03:00
CInfoBar :: EmptyVisibleInfo :: EmptyVisibleInfo ()
2012-06-13 13:04:06 +00:00
{
}
2018-04-07 14:34:11 +03:00
CInfoBar :: VisibleHeroInfo :: VisibleHeroInfo ( const CGHeroInstance * hero )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE );
background = std :: make_shared < CPicture > ( "ADSTATHR" );
heroTooltip = std :: make_shared < CHeroTooltip > ( Point ( 0 , 0 ), hero );
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
CInfoBar :: VisibleTownInfo :: VisibleTownInfo ( const CGTownInstance * town )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE );
background = std :: make_shared < CPicture > ( "ADSTATCS" );
townTooltip = std :: make_shared < CTownTooltip > ( Point ( 0 , 0 ), town );
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
CInfoBar :: VisibleDateInfo :: VisibleDateInfo ()
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE );
2012-06-13 13:04:06 +00: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
2012-06-13 13:04:06 +00:00
std :: string labelText ;
2018-04-07 14:34:11 +03: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
2013-02-02 08:29:57 +00:00
labelText = CGI -> generaltexth -> allTexts [ 63 ] + " " + boost :: lexical_cast < std :: string > ( LOCPLINT -> cb -> getDate ( Date :: WEEK ));
2012-06-13 13:04:06 +00:00
else
2013-02-02 08:29:57 +00:00
labelText = CGI -> generaltexth -> allTexts [ 64 ] + " " + boost :: lexical_cast < std :: string > ( LOCPLINT -> cb -> getDate ( Date :: DAY_OF_WEEK ));
2012-06-13 13:04:06 +00: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 14:34:11 +03:00
forceRefresh . push_back ( label );
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
std :: string CInfoBar :: VisibleDateInfo :: getNewDayName ()
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
if ( LOCPLINT -> cb -> getDate ( Date :: DAY ) == 1 )
return "NEWDAY" ;
2012-06-13 13:04:06 +00:00
2018-04-07 14:34:11 +03:00
if ( LOCPLINT -> cb -> getDate ( Date :: DAY ) != 1 )
return "NEWDAY" ;
2012-06-13 13:04:06 +00:00
2018-04-07 14:34:11 +03:00
switch ( LOCPLINT -> cb -> getDate ( Date :: WEEK ))
{
case 1 :
return "NEWWEEK1" ;
case 2 :
return "NEWWEEK2" ;
case 3 :
return "NEWWEEK3" ;
case 4 :
return "NEWWEEK4" ;
default :
return "" ;
}
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
CInfoBar :: VisibleEnemyTurnInfo :: VisibleEnemyTurnInfo ( PlayerColor player )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE );
background = std :: make_shared < CPicture > ( "ADSTATNX" );
banner = std :: make_shared < CAnimImage > ( "CREST58" , player . getNum (), 0 , 20 , 51 );
2023-01-27 12:22:48 +02:00
sand = std :: make_shared < CShowableAnim > ( 99 , 51 , "HOURSAND" , 0 , 100 ); // H3 uses around 100 ms per frame
glass = std :: make_shared < CShowableAnim > ( 99 , 51 , "HOURGLAS" , CShowableAnim :: PLAY_ONCE , 1000 ); // H3 scales this nicely for AI turn duration, don't have anything like that in vcmi
2018-04-07 14:34:11 +03:00
}
2012-06-13 13:04:06 +00:00
2018-04-07 14:34:11 +03:00
CInfoBar :: VisibleGameStatusInfo :: VisibleGameStatusInfo ()
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE );
2012-06-13 13:04:06 +00:00
//get amount of halls of each level
std :: vector < int > halls ( 4 , 0 );
2013-06-29 13:05:48 +00:00
for ( auto town : LOCPLINT -> towns )
2016-11-26 22:12:52 +03:00
{
int hallLevel = town -> hallLevel ();
//negative value means no village hall, unlikely but possible
if ( hallLevel >= 0 )
halls . at ( hallLevel ) ++ ;
}
2012-06-13 13:04:06 +00:00
2013-03-03 17:06:03 +00:00
std :: vector < PlayerColor > allies , enemies ;
2012-06-13 13:04:06 +00:00
//generate list of allies and enemies
2013-03-03 17:06:03 +00:00
for ( int i = 0 ; i < PlayerColor :: PLAYER_LIMIT_I ; i ++ )
2012-06-13 13:04:06 +00:00
{
2013-12-28 18:57:08 +00:00
if ( LOCPLINT -> cb -> getPlayerStatus ( PlayerColor ( i ), false ) == EPlayerStatus :: INGAME )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
if ( LOCPLINT -> cb -> getPlayerRelations ( LOCPLINT -> playerID , PlayerColor ( i )) != PlayerRelations :: ENEMIES )
2013-03-03 17:06:03 +00:00
allies . push_back ( PlayerColor ( i ));
2012-06-13 13:04:06 +00:00
else
2013-03-03 17:06:03 +00:00
enemies . push_back ( PlayerColor ( i ));
2012-06-13 13:04:06 +00:00
}
}
2018-04-07 14:34:11 +03:00
//generate widgets
background = std :: make_shared < CPicture > ( "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 13:04:06 +00:00
int posx = allyLabel -> pos . w + allyLabel -> pos . x - pos . x + 4 ;
2013-06-29 13:05:48 +00:00
for ( PlayerColor & player : allies )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
auto image = std :: make_shared < CAnimImage > ( "ITGFLAGS" , player . getNum (), 0 , posx , 102 );
2012-06-13 13:04:06 +00:00
posx += image -> pos . w ;
2018-04-07 14:34:11 +03:00
flags . push_back ( image );
2012-06-13 13:04:06 +00:00
}
posx = enemyLabel -> pos . w + enemyLabel -> pos . x - pos . x + 4 ;
2013-06-29 13:05:48 +00:00
for ( PlayerColor & player : enemies )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
auto image = std :: make_shared < CAnimImage > ( "ITGFLAGS" , player . getNum (), 0 , posx , 132 );
2012-06-13 13:04:06 +00:00
posx += image -> pos . w ;
2018-04-07 14:34:11 +03:00
flags . push_back ( image );
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
for ( size_t i = 0 ; i < halls . size (); i ++ )
2012-06-13 13:04:06 +00:00
{
2020-10-01 01:38:06 -07:00
hallIcons . push_back ( std :: make_shared < CAnimImage > ( "itmtl" , i , 0 , 6 + 42 * ( int ) i , 11 ));
2018-04-07 14:34:11 +03:00
if ( halls [ i ])
2022-11-26 23:12:20 +02:00
hallLabels . push_back ( std :: make_shared < CLabel > ( 26 + 42 * ( int ) i , 64 , FONT_SMALL , ETextAlignment :: CENTER , Colors :: WHITE , boost :: lexical_cast < std :: string > ( halls [ i ])));
2012-06-13 13:04:06 +00:00
}
}
2018-04-07 14:34:11 +03:00
CInfoBar :: VisibleComponentInfo :: VisibleComponentInfo ( const Component & compToDisplay , std :: string message )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE );
2012-06-13 13:04:06 +00:00
2023-01-30 13:58:13 +02:00
background = std :: make_shared < CPicture > ( "ADSTATOT" , 1 , 0 );
2012-06-13 13:04:06 +00:00
2018-04-07 14:34:11 +03:00
comp = std :: make_shared < CComponent > ( compToDisplay );
2012-09-29 08:35:31 +00:00
comp -> moveTo ( Point ( pos . x + 47 , pos . y + 50 ));
2012-06-13 13:04:06 +00:00
2022-11-26 23:12:20 +02:00
text = std :: make_shared < CTextBox > ( message , Rect ( 10 , 4 , 160 , 50 ), 0 , FONT_SMALL , ETextAlignment :: CENTER , Colors :: WHITE );
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
void CInfoBar :: playNewDaySound ()
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
if ( LOCPLINT -> cb -> getDate ( Date :: DAY_OF_WEEK ) != 1 ) // not first day of the week
CCS -> soundh -> playSound ( soundBase :: newDay );
else if ( LOCPLINT -> cb -> getDate ( Date :: WEEK ) != 1 ) // not first week in month
CCS -> soundh -> playSound ( soundBase :: newWeek );
else if ( LOCPLINT -> cb -> getDate ( Date :: MONTH ) != 1 ) // not first month
CCS -> soundh -> playSound ( soundBase :: newMonth );
else
CCS -> soundh -> playSound ( soundBase :: newDay );
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
void CInfoBar :: reset ()
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
state = EMPTY ;
visibleInfo = std :: make_shared < EmptyVisibleInfo > ();
2012-06-13 13:04:06 +00:00
}
void CInfoBar :: showSelection ()
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
if ( adventureInt -> selection )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
if ( auto hero = dynamic_cast < const CGHeroInstance *> ( adventureInt -> selection ))
2012-06-13 13:04:06 +00:00
{
2012-06-22 11:40:16 +00:00
showHeroSelection ( hero );
2012-06-13 13:04:06 +00:00
return ;
}
2018-04-07 14:34:11 +03:00
else if ( auto town = dynamic_cast < const CGTownInstance *> ( adventureInt -> selection ))
2012-06-13 13:04:06 +00:00
{
2012-06-22 11:40:16 +00:00
showTownSelection ( town );
2012-06-13 13:04:06 +00:00
return ;
}
}
showGameStatus (); //FIXME: may be incorrect but shouldn't happen in general
}
void CInfoBar :: tick ()
{
removeUsedEvents ( TIME );
2017-03-14 00:00:47 +03:00
if ( GH . topInt () == adventureInt )
showSelection ();
2012-06-13 13:04:06 +00:00
}
void CInfoBar :: clickLeft ( tribool down , bool previousState )
{
2018-04-07 14:34:11 +03:00
if ( down )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
if ( state == HERO || state == TOWN )
2012-06-13 13:04:06 +00:00
showGameStatus ();
2018-04-07 14:34:11 +03:00
else if ( state == GAME )
2012-06-13 13:04:06 +00:00
showDate ();
else
showSelection ();
}
}
void CInfoBar :: clickRight ( tribool down , bool previousState )
{
2023-02-10 15:50:46 +02:00
if ( down )
CRClickPopup :: createAndPush ( CGI -> generaltexth -> allTexts [ 109 ]);
2012-06-13 13:04:06 +00:00
}
void CInfoBar :: hover ( bool on )
{
2018-04-07 14:34:11 +03:00
if ( on )
2022-11-18 17:54:10 +02:00
GH . statusbar -> write ( CGI -> generaltexth -> zelp [ 292 ]. first );
2012-06-13 13:04:06 +00:00
else
GH . statusbar -> clear ();
}
2018-04-07 14:34:11 +03:00
CInfoBar :: CInfoBar ( const Rect & position )
: CIntObject ( LCLICK | RCLICK | HOVER , position . topLeft ()),
state ( EMPTY )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE );
2012-06-13 13:04:06 +00:00
pos . w = position . w ;
pos . h = position . h ;
2018-04-07 14:34:11 +03:00
reset ();
2012-06-13 13:04:06 +00:00
}
void CInfoBar :: showDate ()
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
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 13:04:06 +00:00
redraw ();
}
2012-09-26 13:13:39 +00:00
void CInfoBar :: showComponent ( const Component & comp , std :: string message )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
state = COMPONENT ;
visibleInfo = std :: make_shared < VisibleComponentInfo > ( comp , message );
2012-06-13 13:04:06 +00:00
setTimer ( 3000 );
redraw ();
}
2013-03-03 17:06:03 +00:00
void CInfoBar :: startEnemyTurn ( PlayerColor color )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
state = AITURN ;
visibleInfo = std :: make_shared < VisibleEnemyTurnInfo > ( color );
2012-06-13 13:04:06 +00:00
redraw ();
}
2012-06-22 11:40:16 +00:00
void CInfoBar :: showHeroSelection ( const CGHeroInstance * hero )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
if ( ! hero )
{
reset ();
}
else
{
state = HERO ;
visibleInfo = std :: make_shared < VisibleHeroInfo > ( hero );
}
2012-06-13 13:04:06 +00:00
redraw ();
}
2012-06-22 11:40:16 +00:00
void CInfoBar :: showTownSelection ( const CGTownInstance * town )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
if ( ! town )
{
reset ();
}
else
{
state = TOWN ;
visibleInfo = std :: make_shared < VisibleTownInfo > ( town );
}
2012-06-13 13:04:06 +00:00
redraw ();
}
void CInfoBar :: showGameStatus ()
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE );
state = GAME ;
visibleInfo = std :: make_shared < VisibleGameStatusInfo > ();
2012-06-13 13:04:06 +00:00
setTimer ( 3000 );
redraw ();
}
2014-07-13 18:39:45 +03:00