2017-07-13 11:26:03 +03:00
/*
* AdventureMapClasses . cpp , part of VCMI engine
*
* 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 13:04:06 +00:00
# include "StdInc.h"
# include "AdventureMapClasses.h"
2023-01-18 16:54:53 +02:00
# include <SDL_timer.h>
2014-07-15 10:14:49 +03:00
2014-07-13 20:53:37 +03:00
# include "MiscWidgets.h"
2014-07-15 10:14:49 +03:00
# include "CComponent.h"
2022-09-18 15:47:49 +03:00
# include "Images.h"
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
# include "../CMusicHandler.h"
# include "../CPlayerInterface.h"
2018-01-05 20:21:07 +03:00
# include "../mainmenu/CMainMenu.h"
2014-07-13 20:53:37 +03:00
# include "../gui/CGuiHandler.h"
# include "../gui/SDL_Pixels.h"
2014-07-15 10:14:49 +03:00
# include "../windows/InfoWindows.h"
2014-07-13 20:53:37 +03:00
# include "../windows/CAdvmapInterface.h"
2022-12-09 13:38:46 +02:00
# include "../battle/BattleInterfaceClasses.h"
# include "../battle/BattleInterface.h"
2014-07-13 20:53:37 +03:00
# include "../../CCallback.h"
# include "../../lib/StartInfo.h"
# include "../../lib/CGameState.h"
# include "../../lib/CGeneralTextHandler.h"
# include "../../lib/CHeroHandler.h"
# include "../../lib/CModHandler.h"
# include "../../lib/CTownHandler.h"
2023-01-09 01:17:37 +02:00
# include "../../lib/TerrainHandler.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/mapObjects/CGHeroInstance.h"
# include "../../lib/mapping/CMap.h"
2023-01-06 21:01:00 +01:00
# include "ClientCommandManager.h"
2012-06-13 13:04:06 +00:00
2018-04-07 14:34:11 +03:00
CList : : CListItem : : CListItem ( CList * Parent )
: CIntObject ( LCLICK | RCLICK | HOVER ) ,
2015-01-13 20:57:41 +01:00
parent ( Parent ) ,
2018-04-07 14:34:11 +03:00
selection ( )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
defActions = 255 - DISPOSE ;
2012-06-13 13:04:06 +00:00
}
CList : : CListItem : : ~ CListItem ( )
{
}
void CList : : CListItem : : clickRight ( tribool down , bool previousState )
{
if ( down = = true )
showTooltip ( ) ;
}
void CList : : CListItem : : clickLeft ( tribool down , bool previousState )
{
2018-04-07 14:34:11 +03:00
if ( down = = true )
2012-06-13 13:04:06 +00:00
{
//second click on already selected item
2018-04-07 14:34:11 +03:00
if ( parent - > selected = = this - > shared_from_this ( ) )
{
2012-06-13 13:04:06 +00:00
open ( ) ;
2018-04-07 14:34:11 +03:00
}
2012-06-13 13:04:06 +00:00
else
{
//first click - switch selection
2018-04-07 14:34:11 +03:00
parent - > select ( this - > shared_from_this ( ) ) ;
2012-06-13 13:04:06 +00:00
}
}
}
void CList : : CListItem : : hover ( bool on )
{
if ( on )
2022-11-18 17:54:10 +02:00
GH . statusbar - > write ( getHoverText ( ) ) ;
2012-06-13 13:04:06 +00:00
else
GH . statusbar - > clear ( ) ;
}
void CList : : CListItem : : onSelect ( bool on )
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
selection . reset ( ) ;
if ( on )
2012-06-13 13:04:06 +00:00
selection = genSelection ( ) ;
select ( on ) ;
GH . totalRedraw ( ) ;
}
2018-04-07 14:34:11 +03:00
CList : : CList ( int Size , Point position , std : : string btnUp , std : : string btnDown , size_t listAmount , int helpUp , int helpDown , CListBox : : CreateFunc create )
: CIntObject ( 0 , position ) ,
2015-01-13 20:57:41 +01:00
size ( Size ) ,
selected ( nullptr )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
scrollUp = std : : make_shared < CButton > ( Point ( 0 , 0 ) , btnUp , CGI - > generaltexth - > zelp [ helpUp ] ) ;
2020-10-01 01:38:06 -07:00
scrollDown = std : : make_shared < CButton > ( Point ( 0 , scrollUp - > pos . h + 32 * ( int ) size ) , btnDown , CGI - > generaltexth - > zelp [ helpDown ] ) ;
2018-04-07 14:34:11 +03:00
listBox = std : : make_shared < CListBox > ( create , Point ( 1 , scrollUp - > pos . h ) , Point ( 0 , 32 ) , size , listAmount ) ;
2012-06-13 13:04:06 +00:00
//assign callback only after list was created
2018-04-07 14:34:11 +03:00
scrollUp - > addCallback ( std : : bind ( & CListBox : : moveToPrev , listBox ) ) ;
scrollDown - > addCallback ( std : : bind ( & CListBox : : moveToNext , listBox ) ) ;
2014-08-09 15:14:31 +03:00
scrollUp - > addCallback ( std : : bind ( & CList : : update , this ) ) ;
2018-04-07 14:34:11 +03:00
scrollDown - > addCallback ( std : : bind ( & CList : : update , this ) ) ;
2012-06-13 13:04:06 +00:00
update ( ) ;
}
void CList : : update ( )
{
2018-04-07 14:34:11 +03:00
bool onTop = listBox - > getPos ( ) = = 0 ;
bool onBottom = listBox - > getPos ( ) + size > = listBox - > size ( ) ;
2012-06-13 13:04:06 +00:00
scrollUp - > block ( onTop ) ;
scrollDown - > block ( onBottom ) ;
}
2018-04-07 14:34:11 +03:00
void CList : : select ( std : : shared_ptr < CListItem > which )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
if ( selected = = which )
2012-06-13 13:04:06 +00:00
return ;
2018-04-07 14:34:11 +03:00
if ( selected )
2012-06-13 13:04:06 +00:00
selected - > onSelect ( false ) ;
selected = which ;
2018-04-07 14:34:11 +03:00
if ( which )
2012-06-13 13:04:06 +00:00
{
which - > onSelect ( true ) ;
onSelect ( ) ;
}
}
int CList : : getSelectedIndex ( )
{
2020-10-01 01:38:06 -07:00
return static_cast < int > ( listBox - > getIndexOf ( selected ) ) ;
2012-06-13 13:04:06 +00:00
}
void CList : : selectIndex ( int which )
{
2018-04-07 14:34:11 +03:00
if ( which < 0 )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
if ( selected )
2012-06-13 13:04:06 +00:00
select ( nullptr ) ;
}
else
{
2018-04-07 14:34:11 +03:00
listBox - > scrollTo ( which ) ;
2012-06-13 13:04:06 +00:00
update ( ) ;
2018-04-07 14:34:11 +03:00
select ( std : : dynamic_pointer_cast < CListItem > ( listBox - > getItem ( which ) ) ) ;
2012-06-13 13:04:06 +00:00
}
}
void CList : : selectNext ( )
{
2017-05-13 16:57:15 +02:00
int index = getSelectedIndex ( ) + 1 ;
2018-04-07 14:34:11 +03:00
if ( index > = listBox - > size ( ) )
2017-05-13 16:57:15 +02:00
index = 0 ;
selectIndex ( index ) ;
2012-06-13 13:04:06 +00:00
}
void CList : : selectPrev ( )
{
int index = getSelectedIndex ( ) ;
2018-04-07 14:34:11 +03:00
if ( index < = 0 )
2012-06-13 13:04:06 +00:00
selectIndex ( 0 ) ;
else
selectIndex ( index - 1 ) ;
}
CHeroList : : CEmptyHeroItem : : CEmptyHeroItem ( )
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
movement = std : : make_shared < CAnimImage > ( " IMOBIL " , 0 , 0 , 0 , 1 ) ;
portrait = std : : make_shared < CPicture > ( " HPSXXX " , movement - > pos . w + 1 ) ;
mana = std : : make_shared < CAnimImage > ( " IMANA " , 0 , 0 , movement - > pos . w + portrait - > pos . w + 2 , 1 ) ;
2012-06-13 13:04:06 +00:00
pos . w = mana - > pos . w + mana - > pos . x - pos . x ;
2018-04-07 14:34:11 +03:00
pos . h = std : : max ( std : : max < SDLX_Size > ( movement - > pos . h + 1 , mana - > pos . h + 1 ) , portrait - > pos . h ) ;
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
CHeroList : : CHeroItem : : CHeroItem ( CHeroList * parent , const CGHeroInstance * Hero )
: CListItem ( parent ) ,
2015-01-13 20:57:41 +01:00
hero ( Hero )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
movement = std : : make_shared < CAnimImage > ( " IMOBIL " , 0 , 0 , 0 , 1 ) ;
portrait = std : : make_shared < CAnimImage > ( " PortraitsSmall " , hero - > portrait , 0 , movement - > pos . w + 1 ) ;
mana = std : : make_shared < CAnimImage > ( " IMANA " , 0 , 0 , movement - > pos . w + portrait - > pos . w + 2 , 1 ) ;
2012-06-13 13:04:06 +00:00
pos . w = mana - > pos . w + mana - > pos . x - pos . x ;
2014-05-21 20:04:34 +04:00
pos . h = std : : max ( std : : max < SDLX_Size > ( movement - > pos . h + 1 , mana - > pos . h + 1 ) , portrait - > pos . h ) ;
2012-06-13 13:04:06 +00:00
update ( ) ;
}
void CHeroList : : CHeroItem : : update ( )
{
2012-06-16 22:40:28 +00:00
movement - > setFrame ( std : : min < size_t > ( movement - > size ( ) - 1 , hero - > movement / 100 ) ) ;
mana - > setFrame ( std : : min < size_t > ( mana - > size ( ) - 1 , hero - > mana / 5 ) ) ;
2012-06-13 13:04:06 +00:00
redraw ( ) ;
}
2018-04-07 14:34:11 +03:00
std : : shared_ptr < CIntObject > CHeroList : : CHeroItem : : genSelection ( )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
return std : : make_shared < CPicture > ( " HPSYYY " , movement - > pos . w + 1 ) ;
2012-06-13 13:04:06 +00:00
}
void CHeroList : : CHeroItem : : select ( bool on )
{
2018-04-07 14:34:11 +03:00
if ( on & & adventureInt - > selection ! = hero )
adventureInt - > select ( hero ) ;
2012-06-13 13:04:06 +00:00
}
void CHeroList : : CHeroItem : : open ( )
{
LOCPLINT - > openHeroWindow ( hero ) ;
}
void CHeroList : : CHeroItem : : showTooltip ( )
{
2023-01-27 00:27:06 +02:00
CRClickPopup : : createAndPush ( hero , GH . getCursorPosition ( ) ) ;
2012-06-13 13:04:06 +00:00
}
std : : string CHeroList : : CHeroItem : : getHoverText ( )
{
2023-01-02 13:27:03 +02:00
return boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 15 ] ) % hero - > getNameTranslated ( ) % hero - > type - > heroClass - > getNameTranslated ( ) ) ;
2012-06-13 13:04:06 +00:00
}
2018-04-07 14:34:11 +03:00
std : : shared_ptr < CIntObject > CHeroList : : createHeroItem ( size_t index )
2012-06-13 13:04:06 +00:00
{
if ( LOCPLINT - > wanderingHeroes . size ( ) > index )
2018-04-07 14:34:11 +03:00
return std : : make_shared < CHeroItem > ( this , LOCPLINT - > wanderingHeroes [ index ] ) ;
return std : : make_shared < CEmptyHeroItem > ( ) ;
2012-06-13 13:04:06 +00:00
}
CHeroList : : CHeroList ( int size , Point position , std : : string btnUp , std : : string btnDown ) :
2015-01-13 20:57:41 +01:00
CList ( size , position , btnUp , btnDown , LOCPLINT - > wanderingHeroes . size ( ) , 303 , 304 , std : : bind ( & CHeroList : : createHeroItem , this , _1 ) )
2012-06-13 13:04:06 +00:00
{
}
void CHeroList : : select ( const CGHeroInstance * hero )
{
selectIndex ( vstd : : find_pos ( LOCPLINT - > wanderingHeroes , hero ) ) ;
}
void CHeroList : : update ( const CGHeroInstance * hero )
{
2012-06-16 22:40:28 +00:00
//this hero is already present, update its status
2018-04-07 14:34:11 +03:00
for ( auto & elem : listBox - > getItems ( ) )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
auto item = std : : dynamic_pointer_cast < CHeroItem > ( elem ) ;
if ( item & & item - > hero = = hero & & vstd : : contains ( LOCPLINT - > wanderingHeroes , hero ) )
2012-06-13 13:04:06 +00:00
{
2012-06-16 22:40:28 +00:00
item - > update ( ) ;
return ;
2012-06-13 13:04:06 +00:00
}
}
//simplest solution for now: reset list and restore selection
2018-04-07 14:34:11 +03:00
listBox - > resize ( LOCPLINT - > wanderingHeroes . size ( ) ) ;
2012-06-13 13:04:06 +00:00
if ( adventureInt - > selection )
{
2018-10-29 16:56:14 +01:00
auto selectedHero = dynamic_cast < const CGHeroInstance * > ( adventureInt - > selection ) ;
if ( selectedHero )
select ( selectedHero ) ;
2012-06-13 13:04:06 +00:00
}
CList : : update ( ) ;
}
2018-04-07 14:34:11 +03:00
std : : shared_ptr < CIntObject > CTownList : : createTownItem ( size_t index )
2012-06-13 13:04:06 +00:00
{
if ( LOCPLINT - > towns . size ( ) > index )
2018-04-07 14:34:11 +03:00
return std : : make_shared < CTownItem > ( this , LOCPLINT - > towns [ index ] ) ;
return std : : make_shared < CAnimImage > ( " ITPA " , 0 ) ;
2012-06-13 13:04:06 +00:00
}
CTownList : : CTownItem : : CTownItem ( CTownList * parent , const CGTownInstance * Town ) :
2015-01-13 20:57:41 +01:00
CListItem ( parent ) ,
town ( Town )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
picture = std : : make_shared < CAnimImage > ( " ITPA " , 0 ) ;
2012-06-13 13:04:06 +00:00
pos = picture - > pos ;
update ( ) ;
}
2018-04-07 14:34:11 +03:00
std : : shared_ptr < CIntObject > CTownList : : CTownItem : : genSelection ( )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
return std : : make_shared < CAnimImage > ( " ITPA " , 1 ) ;
2012-06-13 13:04:06 +00:00
}
void CTownList : : CTownItem : : update ( )
{
2012-09-22 15:10:15 +00:00
size_t iconIndex = town - > town - > clientInfo . icons [ town - > hasFort ( ) ] [ town - > builded > = CGI - > modh - > settings . MAX_BUILDING_PER_TURN ] ;
2012-06-13 13:04:06 +00:00
2012-12-03 16:00:17 +00:00
picture - > setFrame ( iconIndex + 2 ) ;
2012-06-13 13:04:06 +00:00
redraw ( ) ;
}
void CTownList : : CTownItem : : select ( bool on )
{
if ( on & & adventureInt - > selection ! = town )
adventureInt - > select ( town ) ;
}
void CTownList : : CTownItem : : open ( )
{
LOCPLINT - > openTownWindow ( town ) ;
}
void CTownList : : CTownItem : : showTooltip ( )
{
2023-01-27 00:27:06 +02:00
CRClickPopup : : createAndPush ( town , GH . getCursorPosition ( ) ) ;
2012-06-13 13:04:06 +00:00
}
std : : string CTownList : : CTownItem : : getHoverText ( )
{
2014-06-24 20:39:36 +03:00
return town - > getObjectName ( ) ;
2012-06-13 13:04:06 +00:00
}
CTownList : : CTownList ( int size , Point position , std : : string btnUp , std : : string btnDown ) :
2015-01-13 20:57:41 +01:00
CList ( size , position , btnUp , btnDown , LOCPLINT - > towns . size ( ) , 306 , 307 , std : : bind ( & CTownList : : createTownItem , this , _1 ) )
2012-06-13 13:04:06 +00:00
{
}
void CTownList : : select ( const CGTownInstance * town )
{
selectIndex ( vstd : : find_pos ( LOCPLINT - > towns , town ) ) ;
}
void CTownList : : update ( const CGTownInstance * )
{
//simplest solution for now: reset list and restore selection
2018-04-07 14:34:11 +03:00
listBox - > resize ( LOCPLINT - > towns . size ( ) ) ;
2012-06-13 13:04:06 +00:00
if ( adventureInt - > selection )
{
auto town = dynamic_cast < const CGTownInstance * > ( adventureInt - > selection ) ;
if ( town )
select ( town ) ;
}
CList : : update ( ) ;
}
const SDL_Color & CMinimapInstance : : getTileColor ( const int3 & pos )
{
static const SDL_Color fogOfWar = { 0 , 0 , 0 , 255 } ;
const TerrainTile * tile = LOCPLINT - > cb - > getTile ( pos , false ) ;
// if tile is not visible it will be black on minimap
if ( ! tile )
return fogOfWar ;
// if object at tile is owned - it will be colored as its owner
2014-10-01 14:19:03 +02:00
for ( const CGObjectInstance * obj : tile - > blockingObjects )
2012-06-13 13:04:06 +00:00
{
//heroes will be blitted later
2014-10-01 14:19:03 +02:00
switch ( obj - > ID )
{
case Obj : : HERO :
case Obj : : PRISON :
continue ;
}
2012-06-13 13:04:06 +00:00
2013-03-03 17:06:03 +00:00
PlayerColor player = obj - > getOwner ( ) ;
if ( player = = PlayerColor : : NEUTRAL )
2012-06-13 13:04:06 +00:00
return * graphics - > neutralColor ;
else
2013-03-03 17:06:03 +00:00
if ( player < PlayerColor : : PLAYER_LIMIT )
return graphics - > playerColors [ player . getNum ( ) ] ;
2012-06-13 13:04:06 +00:00
}
// else - use terrain color (blocked version or normal)
2023-01-01 17:10:47 +02:00
const auto & colorPair = parent - > colors . find ( tile - > terType - > getId ( ) ) - > second ;
2012-06-13 13:04:06 +00:00
if ( tile - > blocked & & ( ! tile - > visitable ) )
2022-09-21 11:34:23 +02:00
return colorPair . second ;
2012-06-13 13:04:06 +00:00
else
2022-09-21 11:34:23 +02:00
return colorPair . first ;
2012-06-13 13:04:06 +00:00
}
2012-07-08 16:36:20 +00:00
void CMinimapInstance : : tileToPixels ( const int3 & tile , int & x , int & y , int toX , int toY )
2012-06-13 13:04:06 +00:00
{
int3 mapSizes = LOCPLINT - > cb - > getMapSize ( ) ;
double stepX = double ( pos . w ) / mapSizes . x ;
double stepY = double ( pos . h ) / mapSizes . y ;
2020-10-01 01:38:06 -07:00
x = static_cast < int > ( toX + stepX * tile . x ) ;
y = static_cast < int > ( toY + stepY * tile . y ) ;
2012-07-08 16:36:20 +00:00
}
void CMinimapInstance : : blitTileWithColor ( const SDL_Color & color , const int3 & tile , SDL_Surface * to , int toX , int toY )
{
2012-06-13 13:04:06 +00:00
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
2012-07-08 16:36:20 +00:00
int xBegin , yBegin , xEnd , yEnd ;
tileToPixels ( tile , xBegin , yBegin , toX , toY ) ;
tileToPixels ( int3 ( tile . x + 1 , tile . y + 1 , tile . z ) , xEnd , yEnd , toX , toY ) ;
2012-06-13 13:04:06 +00:00
for ( int y = yBegin ; y < yEnd ; y + + )
{
Uint8 * ptr = ( Uint8 * ) to - > pixels + y * to - > pitch + xBegin * minimap - > format - > BytesPerPixel ;
for ( int x = xBegin ; x < xEnd ; x + + )
ColorPutter < 4 , 1 > : : PutColor ( ptr , color ) ;
}
}
void CMinimapInstance : : refreshTile ( const int3 & tile )
{
blitTileWithColor ( getTileColor ( int3 ( tile . x , tile . y , level ) ) , tile , minimap , 0 , 0 ) ;
}
void CMinimapInstance : : drawScaled ( int level )
{
int3 mapSizes = LOCPLINT - > cb - > getMapSize ( ) ;
//size of one map tile on our minimap
double stepX = double ( pos . w ) / mapSizes . x ;
double stepY = double ( pos . h ) / mapSizes . y ;
double currY = 0 ;
for ( int y = 0 ; y < mapSizes . y ; y + + , currY + = stepY )
{
double currX = 0 ;
for ( int x = 0 ; x < mapSizes . x ; x + + , currX + = stepX )
{
const SDL_Color & color = getTileColor ( int3 ( x , y , level ) ) ;
//coordinates of rectangle on minimap representing this tile
// begin - first to blit, end - first NOT to blit
2020-10-01 01:38:06 -07:00
int xBegin = static_cast < int > ( currX ) ;
int yBegin = static_cast < int > ( currY ) ;
int xEnd = static_cast < int > ( currX + stepX ) ;
int yEnd = static_cast < int > ( currY + stepY ) ;
2012-06-13 13:04:06 +00:00
for ( int y = yBegin ; y < yEnd ; y + + )
{
Uint8 * ptr = ( Uint8 * ) minimap - > pixels + y * minimap - > pitch + xBegin * minimap - > format - > BytesPerPixel ;
for ( int x = xBegin ; x < xEnd ; x + + )
ColorPutter < 4 , 1 > : : PutColor ( ptr , color ) ;
}
}
}
}
CMinimapInstance : : CMinimapInstance ( CMinimap * Parent , int Level ) :
2015-01-13 20:57:41 +01:00
parent ( Parent ) ,
minimap ( CSDL_Ext : : createSurfaceWithBpp < 4 > ( parent - > pos . w , parent - > pos . h ) ) ,
level ( Level )
2012-06-13 13:04:06 +00:00
{
pos . w = parent - > pos . w ;
pos . h = parent - > pos . h ;
drawScaled ( level ) ;
}
CMinimapInstance : : ~ CMinimapInstance ( )
{
SDL_FreeSurface ( minimap ) ;
}
2018-04-07 14:34:11 +03:00
void CMinimapInstance : : showAll ( SDL_Surface * to )
2012-06-13 13:04:06 +00:00
{
blitAtLoc ( minimap , 0 , 0 , to ) ;
//draw heroes
2015-01-13 20:57:41 +01:00
std : : vector < const CGHeroInstance * > heroes = LOCPLINT - > cb - > getHeroesInfo ( false ) ; //TODO: do we really need separate function for drawing heroes?
2013-06-29 13:05:48 +00:00
for ( auto & hero : heroes )
2012-06-13 13:04:06 +00:00
{
2022-12-07 22:10:08 +02:00
int3 position = hero - > visitablePos ( ) ;
2018-04-07 14:34:11 +03:00
if ( position . z = = level )
2012-06-13 13:04:06 +00:00
{
2013-03-03 17:06:03 +00:00
const SDL_Color & color = graphics - > playerColors [ hero - > getOwner ( ) . getNum ( ) ] ;
2012-06-13 13:04:06 +00:00
blitTileWithColor ( color , position , to , pos . x , pos . y ) ;
}
}
}
2022-09-29 11:44:46 +02:00
std : : map < TerrainId , std : : pair < SDL_Color , SDL_Color > > CMinimap : : loadColors ( )
2012-06-13 13:04:06 +00:00
{
2022-09-29 11:44:46 +02:00
std : : map < TerrainId , std : : pair < SDL_Color , SDL_Color > > ret ;
2012-06-13 13:04:06 +00:00
2022-12-20 16:14:06 +02:00
for ( const auto & terrain : CGI - > terrainTypeHandler - > objects )
2012-06-13 13:04:06 +00:00
{
SDL_Color normal =
{
2022-12-20 16:14:06 +02:00
ui8 ( terrain - > minimapUnblocked [ 0 ] ) ,
ui8 ( terrain - > minimapUnblocked [ 1 ] ) ,
ui8 ( terrain - > minimapUnblocked [ 2 ] ) ,
2012-06-13 13:04:06 +00:00
ui8 ( 255 )
} ;
SDL_Color blocked =
{
2022-12-20 16:14:06 +02:00
ui8 ( terrain - > minimapBlocked [ 0 ] ) ,
ui8 ( terrain - > minimapBlocked [ 1 ] ) ,
ui8 ( terrain - > minimapBlocked [ 2 ] ) ,
2012-06-13 13:04:06 +00:00
ui8 ( 255 )
} ;
2023-01-01 17:10:47 +02:00
ret [ terrain - > getId ( ) ] = std : : make_pair ( normal , blocked ) ;
2012-06-13 13:04:06 +00:00
}
return ret ;
}
2018-04-07 14:34:11 +03:00
CMinimap : : CMinimap ( const Rect & position )
: CIntObject ( LCLICK | RCLICK | HOVER | MOVE , position . topLeft ( ) ) ,
2015-01-13 20:57:41 +01:00
level ( 0 ) ,
2022-06-20 17:39:50 +03:00
colors ( loadColors ( ) )
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
aiShield = std : : make_shared < CPicture > ( " AIShield " ) ;
aiShield - > disable ( ) ;
2012-06-13 13:04:06 +00:00
}
2012-07-08 16:36:20 +00:00
int3 CMinimap : : translateMousePosition ( )
2012-06-13 13:04:06 +00:00
{
// 0 = top-left corner, 1 = bottom-right corner
2023-01-27 00:27:06 +02:00
double dx = double ( GH . getCursorPosition ( ) . x - pos . x ) / pos . w ;
double dy = double ( GH . getCursorPosition ( ) . y - pos . y ) / pos . h ;
2012-06-13 13:04:06 +00:00
int3 mapSizes = LOCPLINT - > cb - > getMapSize ( ) ;
2020-10-01 01:38:06 -07:00
int3 tile ( ( si32 ) ( mapSizes . x * dx ) , ( si32 ) ( mapSizes . y * dy ) , level ) ;
2012-07-08 16:36:20 +00:00
return tile ;
}
2012-06-13 13:04:06 +00:00
2012-07-08 16:36:20 +00:00
void CMinimap : : moveAdvMapSelection ( )
{
int3 newLocation = translateMousePosition ( ) ;
2012-06-13 13:04:06 +00:00
adventureInt - > centerOn ( newLocation ) ;
2012-08-07 11:28:52 +00:00
if ( ! ( adventureInt - > active & GENERAL ) )
GH . totalRedraw ( ) ; //redraw this as well as inactive adventure map
else
redraw ( ) ; //redraw only this
2012-06-13 13:04:06 +00:00
}
void CMinimap : : clickLeft ( tribool down , bool previousState )
{
2018-04-07 14:34:11 +03:00
if ( down )
2012-06-13 13:04:06 +00:00
moveAdvMapSelection ( ) ;
}
void CMinimap : : clickRight ( tribool down , bool previousState )
{
adventureInt - > handleRightClick ( CGI - > generaltexth - > zelp [ 291 ] . second , down ) ;
}
void CMinimap : : 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 [ 291 ] . first ) ;
2012-06-13 13:04:06 +00:00
else
GH . statusbar - > clear ( ) ;
}
void CMinimap : : mouseMoved ( const SDL_MouseMotionEvent & sEvent )
{
2017-06-08 21:07:09 +02:00
if ( mouseState ( EIntObjMouseBtnType : : LEFT ) )
2012-06-13 13:04:06 +00:00
moveAdvMapSelection ( ) ;
}
void CMinimap : : showAll ( SDL_Surface * to )
{
CIntObject : : showAll ( to ) ;
2018-04-07 14:34:11 +03:00
if ( minimap )
2012-06-13 13:04:06 +00:00
{
int3 mapSizes = LOCPLINT - > cb - > getMapSize ( ) ;
2015-01-13 20:57:41 +01:00
int3 tileCountOnScreen = adventureInt - > terrain . tileCountOnScreen ( ) ;
2012-06-13 13:04:06 +00:00
//draw radar
2023-01-17 22:01:35 +02:00
Rect oldClip ;
Rect radar =
2012-06-13 13:04:06 +00:00
{
si16 ( adventureInt - > position . x * pos . w / mapSizes . x + pos . x ) ,
si16 ( adventureInt - > position . y * pos . h / mapSizes . y + pos . y ) ,
2015-01-13 20:57:41 +01:00
ui16 ( tileCountOnScreen . x * pos . w / mapSizes . x ) ,
ui16 ( tileCountOnScreen . y * pos . h / mapSizes . y )
2012-06-13 13:04:06 +00:00
} ;
2018-04-07 14:34:11 +03:00
if ( adventureInt - > mode = = EAdvMapMode : : WORLD_VIEW )
2015-01-17 13:41:59 +01:00
{
// adjusts radar so that it doesn't go out of map in world view mode (since there's no frame)
2015-02-01 19:25:42 +01:00
radar . x = std : : min < int > ( std : : max ( pos . x , radar . x ) , pos . x + pos . w - radar . w ) ;
radar . y = std : : min < int > ( std : : max ( pos . y , radar . y ) , pos . y + pos . h - radar . h ) ;
2015-01-17 13:41:59 +01:00
2018-04-07 14:34:11 +03:00
if ( radar . x < pos . x & & radar . y < pos . y )
2015-01-17 13:41:59 +01:00
return ; // whole map is visible at once, no point in redrawing border
}
2023-01-17 22:01:35 +02:00
CSDL_Ext : : getClipRect ( to , oldClip ) ;
CSDL_Ext : : setClipRect ( to , pos ) ;
CSDL_Ext : : drawDashedBorder ( to , radar , Colors : : PURPLE ) ;
CSDL_Ext : : setClipRect ( to , oldClip ) ;
2012-06-13 13:04:06 +00:00
}
}
void CMinimap : : update ( )
{
2018-04-07 14:34:11 +03:00
if ( aiShield - > recActions & UPDATE ) //AI turn is going on. There is no need to update minimap
2012-06-13 13:04:06 +00:00
return ;
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
minimap = std : : make_shared < CMinimapInstance > ( this , level ) ;
2012-06-15 17:08:19 +00:00
redraw ( ) ;
2012-06-13 13:04:06 +00:00
}
void CMinimap : : setLevel ( int newLevel )
{
level = newLevel ;
update ( ) ;
}
void CMinimap : : setAIRadar ( bool on )
{
2018-04-07 14:34:11 +03:00
if ( on )
2012-06-13 13:04:06 +00:00
{
2018-04-07 14:34:11 +03:00
aiShield - > enable ( ) ;
minimap . reset ( ) ;
2012-06-13 13:04:06 +00:00
}
else
{
2018-04-07 14:34:11 +03:00
aiShield - > disable ( ) ;
2012-06-13 13:04:06 +00:00
update ( ) ;
}
2013-12-19 17:29:35 +00:00
// this my happen during AI turn when this interface is inactive
// force redraw in order to properly update interface
GH . totalRedraw ( ) ;
2012-06-13 13:04:06 +00:00
}
void CMinimap : : hideTile ( const int3 & pos )
{
2018-04-07 14:34:11 +03:00
if ( minimap )
2012-06-13 13:04:06 +00:00
minimap - > refreshTile ( pos ) ;
}
void CMinimap : : showTile ( const int3 & pos )
{
2018-04-07 14:34:11 +03:00
if ( minimap )
2012-06-13 13:04:06 +00:00
minimap - > refreshTile ( pos ) ;
}
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
2018-04-07 14:34:11 +03:00
background = std : : make_shared < CPicture > ( " ADSTATOT " , 1 ) ;
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 )
{
adventureInt - > handleRightClick ( CGI - > generaltexth - > allTexts [ 109 ] , down ) ;
}
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
2018-04-07 14:34:11 +03:00
CInGameConsole : : CInGameConsole ( )
: CIntObject ( KEYBOARD | TEXTINPUT ) ,
prevEntDisp ( - 1 ) ,
defaultTimeout ( 10000 ) ,
maxDisplayedTexts ( 10 )
{
}
2014-07-13 18:39:45 +03:00
void CInGameConsole : : show ( SDL_Surface * to )
{
int number = 0 ;
2020-10-01 01:38:06 -07:00
std : : vector < std : : list < std : : pair < std : : string , Uint32 > > : : iterator > toDel ;
2014-07-13 18:39:45 +03:00
boost : : unique_lock < boost : : mutex > lock ( texts_mx ) ;
for ( auto it = texts . begin ( ) ; it ! = texts . end ( ) ; + + it , + + number )
{
2022-12-21 17:02:53 +02:00
Point leftBottomCorner ( 0 , pos . h ) ;
2014-07-13 18:39:45 +03:00
graphics - > fonts [ FONT_MEDIUM ] - > renderTextLeft ( to , it - > first , Colors : : GREEN ,
2020-10-01 01:38:06 -07:00
Point ( leftBottomCorner . x + 50 , leftBottomCorner . y - ( int ) texts . size ( ) * 20 - 80 + number * 20 ) ) ;
2014-07-13 18:39:45 +03:00
2020-10-01 01:38:06 -07:00
if ( ( int ) ( SDL_GetTicks ( ) - it - > second ) > defaultTimeout )
2014-07-13 18:39:45 +03:00
{
toDel . push_back ( it ) ;
}
}
for ( auto & elem : toDel )
{
texts . erase ( elem ) ;
}
}
void CInGameConsole : : print ( const std : : string & txt )
{
boost : : unique_lock < boost : : mutex > lock ( texts_mx ) ;
int lineLen = conf . go ( ) - > ac . outputLineLength ;
if ( txt . size ( ) < lineLen )
{
texts . push_back ( std : : make_pair ( txt , SDL_GetTicks ( ) ) ) ;
if ( texts . size ( ) > maxDisplayedTexts )
{
texts . pop_front ( ) ;
}
}
else
{
assert ( lineLen ) ;
for ( int g = 0 ; g < txt . size ( ) / lineLen + 1 ; + + g )
{
std : : string part = txt . substr ( g * lineLen , lineLen ) ;
if ( part . size ( ) = = 0 )
break ;
texts . push_back ( std : : make_pair ( part , SDL_GetTicks ( ) ) ) ;
if ( texts . size ( ) > maxDisplayedTexts )
{
texts . pop_front ( ) ;
}
}
}
}
void CInGameConsole : : keyPressed ( const SDL_KeyboardEvent & key )
{
if ( key . type ! = SDL_KEYDOWN ) return ;
if ( ! captureAllKeys & & key . keysym . sym ! = SDLK_TAB ) return ; //because user is not entering any text
switch ( key . keysym . sym )
{
case SDLK_TAB :
case SDLK_ESCAPE :
{
if ( captureAllKeys )
{
endEnteringText ( false ) ;
}
2017-10-29 18:23:30 +03:00
else if ( SDLK_TAB = = key . keysym . sym )
2014-07-13 18:39:45 +03:00
{
startEnteringText ( ) ;
}
break ;
}
case SDLK_RETURN : //enter key
{
2023-01-22 01:14:28 +01:00
if ( ! enteredText . empty ( ) & & captureAllKeys )
2014-07-13 18:39:45 +03:00
{
2023-01-22 01:14:28 +01:00
bool anyTextExceptCaret = enteredText . size ( ) > 1 ;
endEnteringText ( anyTextExceptCaret ) ;
if ( anyTextExceptCaret )
{
CCS - > soundh - > playSound ( " CHAT " ) ;
}
2014-07-13 18:39:45 +03:00
}
break ;
}
case SDLK_BACKSPACE :
{
if ( enteredText . size ( ) > 1 )
{
Unicode : : trimRight ( enteredText , 2 ) ;
enteredText + = ' _ ' ;
refreshEnteredText ( ) ;
}
break ;
}
case SDLK_UP : //up arrow
{
if ( previouslyEntered . size ( ) = = 0 )
break ;
if ( prevEntDisp = = - 1 )
{
2020-10-01 01:38:06 -07:00
prevEntDisp = static_cast < int > ( previouslyEntered . size ( ) - 1 ) ;
2014-07-13 18:39:45 +03:00
enteredText = previouslyEntered [ prevEntDisp ] + " _ " ;
refreshEnteredText ( ) ;
}
else if ( prevEntDisp > 0 )
{
- - prevEntDisp ;
enteredText = previouslyEntered [ prevEntDisp ] + " _ " ;
refreshEnteredText ( ) ;
}
break ;
}
case SDLK_DOWN : //down arrow
{
if ( prevEntDisp ! = - 1 & & prevEntDisp + 1 < previouslyEntered . size ( ) )
{
+ + prevEntDisp ;
enteredText = previouslyEntered [ prevEntDisp ] + " _ " ;
refreshEnteredText ( ) ;
}
else if ( prevEntDisp + 1 = = previouslyEntered . size ( ) ) //useful feature
{
prevEntDisp = - 1 ;
enteredText = " _ " ;
refreshEnteredText ( ) ;
}
break ;
}
default :
{
break ;
}
}
}
void CInGameConsole : : textInputed ( const SDL_TextInputEvent & event )
{
if ( ! captureAllKeys | | enteredText . size ( ) = = 0 )
return ;
enteredText . resize ( enteredText . size ( ) - 1 ) ;
enteredText + = event . text ;
enteredText + = " _ " ;
refreshEnteredText ( ) ;
}
void CInGameConsole : : textEdited ( const SDL_TextEditingEvent & event )
{
//do nothing here
}
void CInGameConsole : : startEnteringText ( )
{
2022-12-19 22:53:31 +02:00
if ( ! active )
return ;
2022-12-19 22:04:50 +02:00
if ( captureAllKeys )
return ;
2022-11-20 11:53:46 +02:00
2022-12-12 18:23:41 +02:00
assert ( GH . statusbar ) ;
2022-12-19 22:53:31 +02:00
assert ( currentStatusBar . expired ( ) ) ; //effectively, nullptr check
2014-07-13 18:39:45 +03:00
2022-12-19 22:53:31 +02:00
currentStatusBar = GH . statusbar ;
2022-12-12 18:23:41 +02:00
captureAllKeys = true ;
2014-07-13 18:39:45 +03:00
enteredText = " _ " ;
2022-12-12 18:23:41 +02:00
GH . statusbar - > setEnteringMode ( true ) ;
GH . statusbar - > setEnteredText ( enteredText ) ;
2014-07-13 18:39:45 +03:00
}
2023-01-06 21:01:00 +01:00
void CInGameConsole : : endEnteringText ( bool processEnteredText )
2014-07-13 18:39:45 +03:00
{
2022-11-20 11:53:46 +02:00
captureAllKeys = false ;
2014-07-13 18:39:45 +03:00
prevEntDisp = - 1 ;
2023-01-06 21:01:00 +01:00
if ( processEnteredText )
2014-07-13 18:39:45 +03:00
{
std : : string txt = enteredText . substr ( 0 , enteredText . size ( ) - 1 ) ;
previouslyEntered . push_back ( txt ) ;
2023-01-06 21:01:00 +01:00
2023-01-06 22:53:10 +01:00
if ( txt . at ( 0 ) = = ' / ' )
{
//some commands like gosolo don't work when executed from GUI thread
2023-01-15 01:09:58 +01:00
auto threadFunction = [ = ] ( )
{
ClientCommandManager commandController ;
commandController . processCommand ( txt . substr ( 1 ) , true ) ;
} ;
boost : : thread clientCommandThread ( threadFunction ) ;
2023-01-07 15:42:34 +01:00
clientCommandThread . detach ( ) ;
2023-01-06 22:53:10 +01:00
}
2023-01-08 20:30:57 +01:00
else
LOCPLINT - > cb - > sendMessage ( txt , LOCPLINT - > getSelection ( ) ) ;
2014-07-13 18:39:45 +03:00
}
2022-11-15 03:20:55 +03:00
enteredText . clear ( ) ;
2022-12-19 22:53:31 +02:00
auto statusbar = currentStatusBar . lock ( ) ;
assert ( statusbar ) ;
if ( statusbar )
statusbar - > setEnteringMode ( false ) ;
currentStatusBar . reset ( ) ;
2014-07-13 18:39:45 +03:00
}
void CInGameConsole : : refreshEnteredText ( )
{
2022-12-19 22:53:31 +02:00
auto statusbar = currentStatusBar . lock ( ) ;
assert ( statusbar ) ;
if ( statusbar )
statusbar - > setEnteredText ( enteredText ) ;
2014-07-13 18:39:45 +03:00
}
2015-01-15 00:22:20 +01:00
CAdvMapPanel : : CAdvMapPanel ( SDL_Surface * bg , Point position )
: CIntObject ( ) ,
background ( bg )
{
defActions = 255 ;
recActions = 255 ;
pos . x + = position . x ;
pos . y + = position . y ;
2015-01-29 20:34:53 +01:00
if ( bg )
{
pos . w = bg - > w ;
pos . h = bg - > h ;
}
2015-01-15 00:22:20 +01:00
}
CAdvMapPanel : : ~ CAdvMapPanel ( )
{
if ( background )
SDL_FreeSurface ( background ) ;
}
2018-04-07 14:34:11 +03:00
void CAdvMapPanel : : addChildColorableButton ( std : : shared_ptr < CButton > button )
2015-01-15 00:22:20 +01:00
{
2018-04-07 14:34:11 +03:00
colorableButtons . push_back ( button ) ;
addChildToPanel ( button , ACTIVATE | DEACTIVATE ) ;
2015-01-15 00:22:20 +01:00
}
void CAdvMapPanel : : setPlayerColor ( const PlayerColor & clr )
{
2018-04-07 14:34:11 +03:00
for ( auto & button : colorableButtons )
2015-01-15 00:22:20 +01:00
{
2018-04-07 14:34:11 +03:00
button - > setPlayerColor ( clr ) ;
2015-01-15 00:22:20 +01:00
}
}
void CAdvMapPanel : : showAll ( SDL_Surface * to )
{
2018-04-07 14:34:11 +03:00
if ( background )
2023-01-17 22:01:35 +02:00
CSDL_Ext : : blitAt ( background , pos . x , pos . y , to ) ;
2015-01-15 00:22:20 +01:00
CIntObject : : showAll ( to ) ;
}
2018-04-07 14:34:11 +03:00
void CAdvMapPanel : : addChildToPanel ( std : : shared_ptr < CIntObject > obj , ui8 actions )
2015-01-15 00:22:20 +01:00
{
2018-04-07 14:34:11 +03:00
otherObjects . push_back ( obj ) ;
2015-01-15 00:22:20 +01:00
obj - > recActions | = actions | SHOWALL ;
2018-04-07 14:34:11 +03:00
obj - > recActions & = ~ DISPOSE ;
addChild ( obj . get ( ) , false ) ;
2015-01-15 00:22:20 +01:00
}
2016-10-18 05:46:07 +03:00
CAdvMapWorldViewPanel : : CAdvMapWorldViewPanel ( std : : shared_ptr < CAnimation > _icons , SDL_Surface * bg , Point position , int spaceBottom , const PlayerColor & color )
: CAdvMapPanel ( bg , position ) , icons ( _icons )
2015-01-15 00:22:20 +01:00
{
2018-07-25 01:36:48 +03:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
int fillerHeight = bg ? spaceBottom - pos . y - pos . h : 0 ;
2016-10-18 05:46:07 +03:00
2018-07-25 01:36:48 +03:00
if ( fillerHeight > 0 )
2015-01-29 18:39:46 +01:00
{
2018-07-25 01:36:48 +03:00
backgroundFiller = std : : make_shared < CFilledTexture > ( " DIBOXBCK " , Rect ( 0 , pos . h , pos . w , fillerHeight ) ) ;
2015-01-29 18:39:46 +01:00
}
}
2015-01-15 00:22:20 +01:00
2018-07-25 01:36:48 +03:00
CAdvMapWorldViewPanel : : ~ CAdvMapWorldViewPanel ( ) = default ;
2015-01-15 00:22:20 +01:00
2018-04-07 14:34:11 +03:00
void CAdvMapWorldViewPanel : : recolorIcons ( const PlayerColor & color , int indexOffset )
2015-01-15 00:22:20 +01:00
{
2016-10-18 05:46:07 +03:00
assert ( iconsData . size ( ) = = currentIcons . size ( ) ) ;
2015-01-15 00:22:20 +01:00
2016-10-18 05:46:07 +03:00
for ( size_t idx = 0 ; idx < iconsData . size ( ) ; idx + + )
2015-01-15 00:22:20 +01:00
{
2016-10-18 05:46:07 +03:00
const auto & data = iconsData . at ( idx ) ;
currentIcons [ idx ] - > setFrame ( data . first + indexOffset ) ;
2015-01-15 00:22:20 +01:00
}
}
2016-10-18 05:46:07 +03:00
void CAdvMapWorldViewPanel : : addChildIcon ( std : : pair < int , Point > data , int indexOffset )
2015-01-15 00:22:20 +01:00
{
2018-04-07 14:34:11 +03:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2015-01-15 00:22:20 +01:00
iconsData . push_back ( data ) ;
2018-04-07 14:34:11 +03:00
currentIcons . push_back ( std : : make_shared < CAnimImage > ( icons , data . first + indexOffset , 0 , data . second . x , data . second . y ) ) ;
2015-01-15 00:22:20 +01:00
}