2017-07-13 10:26:03 +02:00
/*
* MiscWidgets . 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
*
*/
2014-07-13 18:40:13 +03:00
# include "StdInc.h"
# include "MiscWidgets.h"
2014-07-15 10:14:49 +03:00
# include "CComponent.h"
2014-07-13 20:53:37 +03:00
# include "../gui/CGuiHandler.h"
2023-01-05 19:34:37 +02:00
# include "../gui/CursorHandler.h"
2014-07-13 18:40:13 +03:00
# include "../CPlayerInterface.h"
# include "../CGameInfo.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/TextControls.h"
2014-07-13 20:53:37 +03:00
# include "../windows/CCastleInterface.h"
2014-07-15 10:14:49 +03:00
# include "../windows/InfoWindows.h"
2023-06-02 15:42:18 +02:00
# include "../render/Canvas.h"
2014-07-13 18:40:13 +03:00
# include "../../CCallback.h"
2023-02-12 23:52:35 +02:00
# include "../../lib/CConfigHandler.h"
2023-06-23 17:02:48 +02:00
# include "../../lib/gameState/InfoAboutArmy.h"
2014-07-13 18:40:13 +03:00
# include "../../lib/CGeneralTextHandler.h"
# include "../../lib/CModHandler.h"
2023-03-15 21:34:29 +02:00
# include "../../lib/GameSettings.h"
2023-02-12 23:52:35 +02:00
# include "../../lib/TextOperations.h"
# include "../../lib/mapObjects/CGHeroInstance.h"
# include "../../lib/mapObjects/CGTownInstance.h"
2014-07-13 18:40:13 +03:00
2014-07-15 10:14:49 +03:00
void CHoverableArea : : hover ( bool on )
2014-07-13 18:40:13 +03:00
{
2014-07-15 10:14:49 +03:00
if ( on )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( hoverText ) ;
2022-11-18 17:54:10 +02:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clearIfMatching ( hoverText ) ;
2014-07-13 18:40:13 +03:00
}
2014-07-15 10:14:49 +03:00
CHoverableArea : : CHoverableArea ( )
2014-07-13 18:40:13 +03:00
{
2014-07-15 10:14:49 +03:00
addUsedEvents ( HOVER ) ;
2014-07-13 18:40:13 +03:00
}
2014-07-15 10:14:49 +03:00
CHoverableArea : : ~ CHoverableArea ( )
2014-07-13 18:40:13 +03:00
{
}
2023-07-09 16:48:25 +02:00
void LRClickableAreaWText : : clickPressed ( const Point & cursorPosition )
2014-07-13 18:40:13 +03:00
{
2023-07-08 13:33:04 +02:00
if ( ! text . empty ( ) )
2014-07-15 10:14:49 +03:00
LOCPLINT - > showInfoDialog ( text ) ;
2014-07-13 18:40:13 +03:00
}
2023-07-08 13:33:04 +02:00
void LRClickableAreaWText : : showPopupWindow ( const Point & cursorPosition )
2014-07-13 18:40:13 +03:00
{
2023-06-11 17:20:10 +02:00
if ( ! text . empty ( ) )
2023-02-10 15:50:46 +02:00
CRClickPopup : : createAndPush ( text ) ;
2014-07-13 18:40:13 +03:00
}
2014-07-15 10:14:49 +03:00
LRClickableAreaWText : : LRClickableAreaWText ( )
2014-07-13 18:40:13 +03:00
{
2014-07-15 10:14:49 +03:00
init ( ) ;
2014-07-13 18:40:13 +03:00
}
2017-07-15 13:08:20 +02:00
LRClickableAreaWText : : LRClickableAreaWText ( const Rect & Pos , const std : : string & HoverText , const std : : string & ClickText )
2014-07-13 18:40:13 +03:00
{
2014-07-15 10:14:49 +03:00
init ( ) ;
2022-12-15 23:24:03 +02:00
pos = Pos + pos . topLeft ( ) ;
2014-07-15 10:14:49 +03:00
hoverText = HoverText ;
text = ClickText ;
2014-07-13 18:40:13 +03:00
}
2014-07-15 10:14:49 +03:00
LRClickableAreaWText : : ~ LRClickableAreaWText ( )
2014-07-13 18:40:13 +03:00
{
}
2014-07-15 10:14:49 +03:00
void LRClickableAreaWText : : init ( )
2014-07-13 18:40:13 +03:00
{
2023-06-13 18:33:35 +02:00
addUsedEvents ( LCLICK | SHOW_POPUP | HOVER ) ;
2014-07-13 18:40:13 +03:00
}
2023-07-09 16:48:25 +02:00
void LRClickableAreaWTextComp : : clickPressed ( const Point & cursorPosition )
2014-07-13 18:40:13 +03:00
{
2023-07-08 13:33:04 +02:00
std : : vector < std : : shared_ptr < CComponent > > comp ( 1 , createComponent ( ) ) ;
LOCPLINT - > showInfoDialog ( text , comp ) ;
2014-07-13 18:40:13 +03:00
}
LRClickableAreaWTextComp : : LRClickableAreaWTextComp ( const Rect & Pos , int BaseType )
2017-10-29 17:23:30 +02:00
: LRClickableAreaWText ( Pos ) , baseType ( BaseType ) , bonusValue ( - 1 )
2014-07-13 18:40:13 +03:00
{
2017-10-29 17:23:30 +02:00
type = - 1 ;
2014-07-13 18:40:13 +03:00
}
2018-04-07 13:34:11 +02:00
std : : shared_ptr < CComponent > LRClickableAreaWTextComp : : createComponent ( ) const
2014-07-13 18:40:13 +03:00
{
if ( baseType > = 0 )
2018-04-07 13:34:11 +02:00
return std : : make_shared < CComponent > ( CComponent : : Etype ( baseType ) , type , bonusValue ) ;
2014-07-13 18:40:13 +03:00
else
2018-04-07 13:34:11 +02:00
return std : : shared_ptr < CComponent > ( ) ;
2014-07-13 18:40:13 +03:00
}
2023-07-08 13:33:04 +02:00
void LRClickableAreaWTextComp : : showPopupWindow ( const Point & cursorPosition )
2014-07-13 18:40:13 +03:00
{
2023-06-11 17:20:10 +02:00
if ( auto comp = createComponent ( ) )
2014-07-13 18:40:13 +03:00
{
2023-06-11 17:20:10 +02:00
CRClickPopup : : createAndPush ( text , CInfoWindow : : TCompsInfo ( 1 , comp ) ) ;
return ;
2014-07-13 18:40:13 +03:00
}
2023-07-08 13:33:04 +02:00
LRClickableAreaWText : : showPopupWindow ( cursorPosition ) ; //only if with-component variant not occurred
2014-07-13 18:40:13 +03:00
}
2018-04-07 13:34:11 +02:00
CHeroArea : : CHeroArea ( int x , int y , const CGHeroInstance * _hero )
2023-06-11 17:20:10 +02:00
: CIntObject ( LCLICK | HOVER ) ,
2018-04-07 13:34:11 +02:00
hero ( _hero )
2014-07-13 18:40:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:40:13 +03:00
2018-04-07 13:34:11 +02:00
pos . x + = x ;
pos . w = 58 ;
pos . y + = y ;
pos . h = 64 ;
2014-07-13 18:40:13 +03:00
2018-04-07 13:34:11 +02:00
if ( hero )
portrait = std : : make_shared < CAnimImage > ( " PortraitsLarge " , hero - > portrait ) ;
2014-07-13 18:40:13 +03:00
}
2023-07-09 16:48:25 +02:00
void CHeroArea : : clickPressed ( const Point & cursorPosition )
2014-07-13 18:40:13 +03:00
{
2023-07-08 13:33:04 +02:00
if ( hero )
2014-07-13 18:40:13 +03:00
LOCPLINT - > openHeroWindow ( hero ) ;
}
void CHeroArea : : hover ( bool on )
{
if ( on & & hero )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( hero - > getObjectName ( ) ) ;
2014-07-13 18:40:13 +03:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2014-07-13 18:40:13 +03:00
}
2023-07-09 16:48:25 +02:00
void LRClickableAreaOpenTown : : clickPressed ( const Point & cursorPosition )
2014-07-13 18:40:13 +03:00
{
2023-07-08 13:33:04 +02:00
if ( town )
2016-11-28 01:09:24 +02:00
{
2014-07-13 18:40:13 +03:00
LOCPLINT - > openTownWindow ( town ) ;
if ( type = = 2 )
LOCPLINT - > castleInt - > builds - > buildingClicked ( BuildingID : : VILLAGE_HALL ) ;
else if ( type = = 3 & & town - > fortLevel ( ) )
LOCPLINT - > castleInt - > builds - > buildingClicked ( BuildingID : : FORT ) ;
2016-11-28 01:09:24 +02:00
}
2014-07-13 18:40:13 +03:00
}
2016-11-27 17:17:20 +02:00
LRClickableAreaOpenTown : : LRClickableAreaOpenTown ( const Rect & Pos , const CGTownInstance * Town )
: LRClickableAreaWTextComp ( Pos , - 1 ) , town ( Town )
2014-07-13 18:40:13 +03:00
{
}
2023-06-02 15:42:18 +02:00
void CMinorResDataBar : : show ( Canvas & to )
2014-07-13 18:40:13 +03:00
{
}
2023-02-03 18:55:25 +02:00
std : : string CMinorResDataBar : : buildDateString ( )
{
std : : string pattern = " %s: %d, %s: %d, %s: %d " ;
auto formatted = boost : : format ( pattern )
2023-02-08 13:56:09 +02:00
% CGI - > generaltexth - > translate ( " core.genrltxt.62 " ) % LOCPLINT - > cb - > getDate ( Date : : MONTH )
% CGI - > generaltexth - > translate ( " core.genrltxt.63 " ) % LOCPLINT - > cb - > getDate ( Date : : WEEK )
% CGI - > generaltexth - > translate ( " core.genrltxt.64 " ) % LOCPLINT - > cb - > getDate ( Date : : DAY_OF_WEEK ) ;
2023-02-03 18:55:25 +02:00
return boost : : str ( formatted ) ;
}
2023-06-02 15:42:18 +02:00
void CMinorResDataBar : : showAll ( Canvas & to )
2014-07-13 18:40:13 +03:00
{
2018-04-07 13:34:11 +02:00
CIntObject : : showAll ( to ) ;
2023-04-27 23:29:16 +02:00
for ( GameResID i = EGameResID : : WOOD ; i < = EGameResID : : GOLD ; + + i )
2014-07-13 18:40:13 +03:00
{
2023-03-09 15:36:46 +02:00
std : : string text = std : : to_string ( LOCPLINT - > cb - > getResourceAmount ( i ) ) ;
2014-07-13 18:40:13 +03:00
2023-06-02 15:42:18 +02:00
Point target ( pos . x + 50 + 76 * GameResID ( i ) , pos . y + pos . h / 2 ) ;
to . drawText ( target , FONT_SMALL , Colors : : WHITE , ETextAlignment : : CENTER , text ) ;
2014-07-13 18:40:13 +03:00
}
2023-06-02 15:42:18 +02:00
Point target ( pos . x + 545 + ( pos . w - 545 ) / 2 , pos . y + pos . h / 2 ) ;
to . drawText ( target , FONT_SMALL , Colors : : WHITE , ETextAlignment : : CENTER , buildDateString ( ) ) ;
2014-07-13 18:40:13 +03:00
}
CMinorResDataBar : : CMinorResDataBar ( )
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:40:13 +03:00
pos . x = 7 ;
pos . y = 575 ;
2018-04-07 13:34:11 +02:00
background = std : : make_shared < CPicture > ( " KRESBAR.bmp " ) ;
background - > colorize ( LOCPLINT - > playerID ) ;
pos . w = background - > pos . w ;
pos . h = background - > pos . h ;
2014-07-13 18:40:13 +03:00
}
2018-04-07 13:34:11 +02:00
CMinorResDataBar : : ~ CMinorResDataBar ( ) = default ;
2014-07-13 18:40:13 +03:00
void CArmyTooltip : : init ( const InfoAboutArmy & army )
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:40:13 +03:00
2022-11-26 23:12:20 +02:00
title = std : : make_shared < CLabel > ( 66 , 2 , FONT_SMALL , ETextAlignment : : TOPLEFT , Colors : : WHITE , army . name ) ;
2014-07-13 18:40:13 +03:00
std : : vector < Point > slotsPos ;
2018-04-07 13:34:11 +02:00
slotsPos . push_back ( Point ( 36 , 73 ) ) ;
slotsPos . push_back ( Point ( 72 , 73 ) ) ;
slotsPos . push_back ( Point ( 108 , 73 ) ) ;
slotsPos . push_back ( Point ( 18 , 122 ) ) ;
slotsPos . push_back ( Point ( 54 , 122 ) ) ;
slotsPos . push_back ( Point ( 90 , 122 ) ) ;
slotsPos . push_back ( Point ( 126 , 122 ) ) ;
2014-07-13 18:40:13 +03:00
for ( auto & slot : army . army )
{
if ( slot . first . getNum ( ) > = GameConstants : : ARMY_SIZE )
{
2017-08-11 13:38:10 +02:00
logGlobal - > warn ( " %s has stack in slot %d " , army . name , slot . first . getNum ( ) ) ;
2014-07-13 18:40:13 +03:00
continue ;
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
icons . push_back ( std : : make_shared < CAnimImage > ( " CPRSMALL " , slot . second . type - > getIconIndex ( ) , 0 , slotsPos [ slot . first . getNum ( ) ] . x , slotsPos [ slot . first . getNum ( ) ] . y ) ) ;
2014-07-13 18:40:13 +03:00
std : : string subtitle ;
if ( army . army . isDetailed )
2018-04-07 13:34:11 +02:00
{
2023-02-12 23:52:35 +02:00
subtitle = TextOperations : : formatMetric ( slot . second . count , 4 ) ;
2018-04-07 13:34:11 +02:00
}
2014-07-13 18:40:13 +03:00
else
{
//if =0 - we have no information about stack size at all
2018-04-07 13:34:11 +02:00
if ( slot . second . count )
2023-01-14 16:55:08 +02:00
{
2023-02-16 00:36:09 +02:00
if ( settings [ " gameTweaks " ] [ " numericCreaturesQuantities " ] . Bool ( ) )
2023-01-14 16:55:08 +02:00
{
subtitle = CCreature : : getQuantityRangeStringForId ( ( CCreature : : CreatureQuantityId ) slot . second . count ) ;
}
else
{
subtitle = CGI - > generaltexth - > arraytxt [ 171 + 3 * ( slot . second . count ) ] ;
}
}
2014-07-13 18:40:13 +03:00
}
2023-03-07 03:19:07 +02:00
subtitles . push_back ( std : : make_shared < CLabel > ( slotsPos [ slot . first . getNum ( ) ] . x + 17 , slotsPos [ slot . first . getNum ( ) ] . y + 39 , FONT_TINY , ETextAlignment : : CENTER , Colors : : WHITE , subtitle ) ) ;
2014-07-13 18:40:13 +03:00
}
}
2018-04-07 13:34:11 +02:00
CArmyTooltip : : CArmyTooltip ( Point pos , const InfoAboutArmy & army ) :
2014-07-13 18:40:13 +03:00
CIntObject ( 0 , pos )
{
init ( army ) ;
}
CArmyTooltip : : CArmyTooltip ( Point pos , const CArmedInstance * army ) :
CIntObject ( 0 , pos )
{
init ( InfoAboutArmy ( army , true ) ) ;
}
2018-04-07 13:34:11 +02:00
void CHeroTooltip : : init ( const InfoAboutHero & hero )
2014-07-13 18:40:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
portrait = std : : make_shared < CAnimImage > ( " PortraitsLarge " , hero . portrait , 0 , 3 , 2 ) ;
2014-07-13 18:40:13 +03:00
if ( hero . details )
{
2018-04-07 13:34:11 +02:00
for ( size_t i = 0 ; i < hero . details - > primskills . size ( ) ; i + + )
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 75 + 28 * ( int ) i , 58 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ,
2023-03-09 15:36:46 +02:00
std : : to_string ( hero . details - > primskills [ i ] ) ) ) ;
2014-07-13 18:40:13 +03:00
2023-03-09 15:36:46 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 158 , 98 , FONT_TINY , ETextAlignment : : CENTER , Colors : : WHITE , std : : to_string ( hero . details - > mana ) ) ) ;
2014-07-13 18:40:13 +03:00
2018-04-07 13:34:11 +02:00
morale = std : : make_shared < CAnimImage > ( " IMRL22 " , hero . details - > morale + 3 , 0 , 5 , 74 ) ;
luck = std : : make_shared < CAnimImage > ( " ILCK22 " , hero . details - > luck + 3 , 0 , 5 , 91 ) ;
2014-07-13 18:40:13 +03:00
}
}
CHeroTooltip : : CHeroTooltip ( Point pos , const InfoAboutHero & hero ) :
CArmyTooltip ( pos , hero )
{
init ( hero ) ;
}
CHeroTooltip : : CHeroTooltip ( Point pos , const CGHeroInstance * hero ) :
2016-09-28 13:22:33 +02:00
CArmyTooltip ( pos , InfoAboutHero ( hero , InfoAboutHero : : EInfoLevel : : DETAILED ) )
2014-07-13 18:40:13 +03:00
{
2016-09-28 13:22:33 +02:00
init ( InfoAboutHero ( hero , InfoAboutHero : : EInfoLevel : : DETAILED ) ) ;
2014-07-13 18:40:13 +03:00
}
2023-07-15 23:14:59 +02:00
CInteractableHeroTooltip : : CInteractableHeroTooltip ( Point pos , const CGHeroInstance * hero ) :
CGarrisonInt ( pos . x , pos . y + 73 , 4 , Point ( 0 , 0 ) , hero , nullptr , true , true , CGarrisonInt : : EGarrisonIntSlotsLayout : : REVERSED_TWO_ROWS )
{
init ( InfoAboutHero ( hero , InfoAboutHero : : EInfoLevel : : DETAILED ) ) ;
}
void CInteractableHeroTooltip : : init ( const InfoAboutHero & hero )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
portrait = std : : make_shared < CAnimImage > ( " PortraitsLarge " , hero . portrait , 0 , 3 , 2 - 73 ) ;
title = std : : make_shared < CLabel > ( 66 , 2 - 73 , FONT_SMALL , ETextAlignment : : TOPLEFT , Colors : : WHITE , hero . name ) ;
if ( hero . details )
{
for ( size_t i = 0 ; i < hero . details - > primskills . size ( ) ; i + + )
labels . push_back ( std : : make_shared < CLabel > ( 75 + 28 * ( int ) i , 58 - 73 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ,
std : : to_string ( hero . details - > primskills [ i ] ) ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 158 , 98 - 73 , FONT_TINY , ETextAlignment : : CENTER , Colors : : WHITE , std : : to_string ( hero . details - > mana ) ) ) ;
morale = std : : make_shared < CAnimImage > ( " IMRL22 " , hero . details - > morale + 3 , 0 , 5 , 74 - 73 ) ;
luck = std : : make_shared < CAnimImage > ( " ILCK22 " , hero . details - > luck + 3 , 0 , 5 , 91 - 73 ) ;
}
}
2018-04-07 13:34:11 +02:00
void CTownTooltip : : init ( const InfoAboutTown & town )
2014-07-13 18:40:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:40:13 +03:00
//order of icons in def: fort, citadel, castle, no fort
size_t fortIndex = town . fortLevel ? town . fortLevel - 1 : 3 ;
2018-04-07 13:34:11 +02:00
fort = std : : make_shared < CAnimImage > ( " ITMCLS " , fortIndex , 0 , 105 , 31 ) ;
2014-07-13 18:40:13 +03:00
assert ( town . tType ) ;
2023-03-15 23:47:26 +02:00
size_t iconIndex = town . tType - > clientInfo . icons [ town . fortLevel > 0 ] [ town . built > = CGI - > settings ( ) - > getInteger ( EGameSettings : : TOWNS_BUILDINGS_PER_TURN_CAP ) ] ;
2014-07-13 18:40:13 +03:00
2018-04-07 13:34:11 +02:00
build = std : : make_shared < CAnimImage > ( " itpt " , iconIndex , 0 , 3 , 2 ) ;
2014-07-13 18:40:13 +03:00
if ( town . details )
{
2023-06-29 07:21:34 +02:00
hall = std : : make_shared < CAnimImage > ( " ITMTLS " , town . details - > hallLevel , 0 , 67 , 31 ) ;
2014-07-13 18:40:13 +03:00
2018-04-07 13:34:11 +02:00
if ( town . details - > goldIncome )
{
2022-11-26 23:12:20 +02:00
income = std : : make_shared < CLabel > ( 157 , 58 , FONT_TINY , ETextAlignment : : CENTER , Colors : : WHITE ,
2023-03-09 15:36:46 +02:00
std : : to_string ( town . details - > goldIncome ) ) ;
2018-04-07 13:34:11 +02:00
}
2014-07-13 18:40:13 +03:00
if ( town . details - > garrisonedHero ) //garrisoned hero icon
2018-04-07 13:34:11 +02:00
garrisonedHero = std : : make_shared < CPicture > ( " TOWNQKGH " , 149 , 76 ) ;
2014-07-13 18:40:13 +03:00
if ( town . details - > customRes ) //silo is built
{
2023-04-05 02:26:29 +02:00
if ( town . tType - > primaryRes = = EGameResID : : WOOD_AND_ORE ) // wood & ore
2014-07-13 18:40:13 +03:00
{
2023-04-05 02:26:29 +02:00
res1 = std : : make_shared < CAnimImage > ( " SMALRES " , GameResID ( EGameResID : : WOOD ) , 0 , 7 , 75 ) ;
res2 = std : : make_shared < CAnimImage > ( " SMALRES " , GameResID ( EGameResID : : ORE ) , 0 , 7 , 88 ) ;
2014-07-13 18:40:13 +03:00
}
else
2018-04-07 13:34:11 +02:00
{
res1 = std : : make_shared < CAnimImage > ( " SMALRES " , town . tType - > primaryRes , 0 , 7 , 81 ) ;
}
2014-07-13 18:40:13 +03:00
}
}
}
2018-04-07 13:34:11 +02:00
CTownTooltip : : CTownTooltip ( Point pos , const InfoAboutTown & town )
: CArmyTooltip ( pos , town )
2014-07-13 18:40:13 +03:00
{
init ( town ) ;
}
2018-04-07 13:34:11 +02:00
CTownTooltip : : CTownTooltip ( Point pos , const CGTownInstance * town )
: CArmyTooltip ( pos , InfoAboutTown ( town , true ) )
2014-07-13 18:40:13 +03:00
{
init ( InfoAboutTown ( town , true ) ) ;
}
2023-07-16 10:17:37 +02:00
CInteractableTownTooltip : : CInteractableTownTooltip ( Point pos , const CGTownInstance * town )
: CGarrisonInt ( pos . x , pos . y + 73 , 4 , Point ( 0 , 0 ) , town - > getUpperArmy ( ) , nullptr , true , true , CGarrisonInt : : EGarrisonIntSlotsLayout : : REVERSED_TWO_ROWS )
{
init ( InfoAboutTown ( town , true ) ) ;
}
void CInteractableTownTooltip : : init ( const InfoAboutTown & town )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
//order of icons in def: fort, citadel, castle, no fort
size_t fortIndex = town . fortLevel ? town . fortLevel - 1 : 3 ;
fort = std : : make_shared < CAnimImage > ( " ITMCLS " , fortIndex , 0 , 105 , 31 - 73 ) ;
assert ( town . tType ) ;
size_t iconIndex = town . tType - > clientInfo . icons [ town . fortLevel > 0 ] [ town . built > = CGI - > settings ( ) - > getInteger ( EGameSettings : : TOWNS_BUILDINGS_PER_TURN_CAP ) ] ;
build = std : : make_shared < CAnimImage > ( " itpt " , iconIndex , 0 , 3 , 2 - 73 ) ;
title = std : : make_shared < CLabel > ( 66 , 2 - 73 , FONT_SMALL , ETextAlignment : : TOPLEFT , Colors : : WHITE , town . name ) ;
if ( town . details )
{
hall = std : : make_shared < CAnimImage > ( " ITMTLS " , town . details - > hallLevel , 0 , 67 , 31 - 73 ) ;
if ( town . details - > goldIncome )
{
income = std : : make_shared < CLabel > ( 157 , 58 - 73 , FONT_TINY , ETextAlignment : : CENTER , Colors : : WHITE ,
std : : to_string ( town . details - > goldIncome ) ) ;
}
if ( town . details - > garrisonedHero ) //garrisoned hero icon
garrisonedHero = std : : make_shared < CPicture > ( " TOWNQKGH " , 149 , 76 - 73 ) ;
if ( town . details - > customRes ) //silo is built
{
if ( town . tType - > primaryRes = = EGameResID : : WOOD_AND_ORE ) // wood & ore
{
res1 = std : : make_shared < CAnimImage > ( " SMALRES " , GameResID ( EGameResID : : WOOD ) , 0 , 7 , 75 - 73 ) ;
res2 = std : : make_shared < CAnimImage > ( " SMALRES " , GameResID ( EGameResID : : ORE ) , 0 , 7 , 88 - 73 ) ;
}
else
{
res1 = std : : make_shared < CAnimImage > ( " SMALRES " , town . tType - > primaryRes , 0 , 7 , 81 - 73 ) ;
}
}
}
}
2023-04-30 17:21:02 +02:00
void MoraleLuckBox : : set ( const AFactionMember * node )
2014-07-13 18:40:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:40:13 +03:00
const int textId [ ] = { 62 , 88 } ; //eg %s \n\n\n {Current Luck Modifiers:}
const int noneTxtId = 108 ; //Russian version uses same text for neutral morale\luck
const int neutralDescr [ ] = { 60 , 86 } ; //eg {Neutral Morale} \n\n Neutral morale means your armies will neither be blessed with extra attacks or freeze in combat.
const int componentType [ ] = { CComponent : : luck , CComponent : : morale } ;
const int hoverTextBase [ ] = { 7 , 4 } ;
2020-11-11 21:43:40 +02:00
TConstBonusListPtr modifierList = std : : make_shared < const BonusList > ( ) ;
bonusValue = 0 ;
2014-07-13 18:40:13 +03:00
2018-04-07 13:34:11 +02:00
if ( node )
2023-05-02 00:05:59 +02:00
bonusValue = morale ? node - > moraleValAndBonusList ( modifierList ) : node - > luckValAndBonusList ( modifierList ) ;
2014-07-13 18:40:13 +03:00
2015-09-04 18:38:42 +02:00
int mrlt = ( bonusValue > 0 ) - ( bonusValue < 0 ) ; //signum: -1 - bad luck / morale, 0 - neutral, 1 - good
2014-07-13 18:40:13 +03:00
hoverText = CGI - > generaltexth - > heroscrn [ hoverTextBase [ morale ] - mrlt ] ;
baseType = componentType [ morale ] ;
text = CGI - > generaltexth - > arraytxt [ textId [ morale ] ] ;
boost : : algorithm : : replace_first ( text , " %s " , CGI - > generaltexth - > arraytxt [ neutralDescr [ morale ] - mrlt ] ) ;
2016-11-27 17:17:20 +02:00
2023-05-01 00:20:01 +02:00
if ( morale & & node & & ( node - > getBonusBearer ( ) - > hasBonusOfType ( BonusType : : UNDEAD )
| | node - > getBonusBearer ( ) - > hasBonusOfType ( BonusType : : NON_LIVING ) ) )
2015-12-24 21:35:32 +02:00
{
text + = CGI - > generaltexth - > arraytxt [ 113 ] ; //unaffected by morale
bonusValue = 0 ;
}
2023-05-01 00:20:01 +02:00
else if ( morale & & node & & node - > getBonusBearer ( ) - > hasBonusOfType ( BonusType : : NO_MORALE ) )
2017-10-05 17:13:49 +02:00
{
2023-05-01 00:20:01 +02:00
auto noMorale = node - > getBonusBearer ( ) - > getBonus ( Selector : : type ( ) ( BonusType : : NO_MORALE ) ) ;
2017-10-05 17:13:49 +02:00
text + = " \n " + noMorale - > Description ( ) ;
bonusValue = 0 ;
}
2023-05-01 00:20:01 +02:00
else if ( ! morale & & node & & node - > getBonusBearer ( ) - > hasBonusOfType ( BonusType : : NO_LUCK ) )
2017-10-05 17:13:49 +02:00
{
2023-05-01 00:20:01 +02:00
auto noLuck = node - > getBonusBearer ( ) - > getBonus ( Selector : : type ( ) ( BonusType : : NO_LUCK ) ) ;
2017-10-05 17:13:49 +02:00
text + = " \n " + noLuck - > Description ( ) ;
bonusValue = 0 ;
}
2014-07-13 18:40:13 +03:00
else
{
2021-02-03 19:19:56 +02:00
std : : string addInfo = " " ;
for ( auto & bonus : * modifierList )
2014-07-13 18:40:13 +03:00
{
2021-03-23 16:47:07 +02:00
if ( bonus - > val )
2021-02-03 19:19:56 +02:00
addInfo + = " \n " + bonus - > Description ( ) ;
2014-07-13 18:40:13 +03:00
}
2021-09-12 13:30:54 +02:00
text = addInfo . empty ( )
? text + CGI - > generaltexth - > arraytxt [ noneTxtId ]
: text + addInfo ;
2014-07-13 18:40:13 +03:00
}
std : : string imageName ;
if ( small )
imageName = morale ? " IMRL30 " : " ILCK30 " ;
else
imageName = morale ? " IMRL42 " : " ILCK42 " ;
2018-04-07 13:34:11 +02:00
image = std : : make_shared < CAnimImage > ( imageName , bonusValue + 3 ) ;
2014-07-13 18:40:13 +03:00
image - > moveBy ( Point ( pos . w / 2 - image - > pos . w / 2 , pos . h / 2 - image - > pos . h / 2 ) ) ; //center icon
}
2018-04-07 13:34:11 +02:00
MoraleLuckBox : : MoraleLuckBox ( bool Morale , const Rect & r , bool Small )
: morale ( Morale ) ,
2014-07-13 18:40:13 +03:00
small ( Small )
{
bonusValue = 0 ;
2022-12-15 23:24:03 +02:00
pos = r + pos . topLeft ( ) ;
2018-04-07 13:34:11 +02:00
defActions = 255 - DISPOSE ;
2014-07-13 18:40:13 +03:00
}
2018-04-07 13:34:11 +02:00
CCreaturePic : : CCreaturePic ( int x , int y , const CCreature * cre , bool Big , bool Animated )
2014-07-13 18:40:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:40:13 +03:00
pos . x + = x ;
pos . y + = y ;
2023-04-09 17:26:32 +02:00
auto faction = cre - > getFaction ( ) ;
2014-07-13 18:40:13 +03:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
assert ( CGI - > townh - > size ( ) > faction ) ;
2014-07-13 18:40:13 +03:00
if ( Big )
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
bg = std : : make_shared < CPicture > ( ( * CGI - > townh ) [ faction ] - > creatureBg130 ) ;
2014-07-13 18:40:13 +03:00
else
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
bg = std : : make_shared < CPicture > ( ( * CGI - > townh ) [ faction ] - > creatureBg120 ) ;
2018-07-25 00:36:48 +02:00
anim = std : : make_shared < CCreatureAnim > ( 0 , 0 , cre - > animDefName ) ;
2014-07-13 18:40:13 +03:00
anim - > clipRect ( cre - > isDoubleWide ( ) ? 170 : 150 , 155 , bg - > pos . w , bg - > pos . h ) ;
2023-05-01 00:20:01 +02:00
anim - > startPreview ( cre - > hasBonusOfType ( BonusType : : SIEGE_WEAPON ) ) ;
2014-07-13 18:40:13 +03:00
2022-11-26 23:12:20 +02:00
amount = std : : make_shared < CLabel > ( bg - > pos . w , bg - > pos . h , FONT_MEDIUM , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE ) ;
2014-09-19 16:31:01 +03:00
2014-07-13 18:40:13 +03:00
pos . w = bg - > pos . w ;
pos . h = bg - > pos . h ;
}
2014-09-19 16:31:01 +03:00
2023-06-02 15:42:18 +02:00
void CCreaturePic : : show ( Canvas & to )
2014-09-19 16:31:01 +03:00
{
// redraw everything in a proper order
bg - > showAll ( to ) ;
anim - > show ( to ) ;
amount - > showAll ( to ) ;
}
void CCreaturePic : : setAmount ( int newAmount )
{
2018-04-07 13:34:11 +02:00
if ( newAmount ! = 0 )
2023-03-09 15:36:46 +02:00
amount - > setText ( std : : to_string ( newAmount ) ) ;
2014-09-19 16:31:01 +03:00
else
amount - > setText ( " " ) ;
}