2017-07-13 10:26:03 +02:00
/*
* GUIClasses . 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
*
*/
2011-12-14 00:23:17 +03:00
# include "StdInc.h"
2009-05-19 21:23:04 +03:00
# include "GUIClasses.h"
2009-05-20 13:08:56 +03:00
# include "CCastleInterface.h"
2011-03-03 20:25:48 +02:00
# include "CCreatureWindow.h"
2009-05-20 13:08:56 +03:00
# include "CHeroWindow.h"
2022-09-18 14:47:49 +02:00
# include "InfoWindows.h"
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
# include "../CMusicHandler.h"
# include "../CPlayerInterface.h"
# include "../CVideoHandler.h"
2018-01-05 19:21:07 +02:00
# include "../CServerHandler.h"
2014-07-13 20:53:37 +03:00
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 "../gui/CGuiHandler.h"
2023-01-05 19:34:37 +02:00
# include "../gui/CursorHandler.h"
2023-02-01 20:42:06 +02:00
# include "../gui/TextAlignment.h"
2023-04-27 19:21:06 +02:00
# include "../gui/Shortcut.h"
2023-05-16 14:10:26 +02:00
# include "../gui/WindowHandler.h"
2014-07-13 20:53:37 +03:00
2014-07-15 10:14:49 +03:00
# include "../widgets/CComponent.h"
2014-07-13 20:53:37 +03:00
# include "../widgets/MiscWidgets.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/CreatureCostBox.h"
# include "../widgets/Buttons.h"
2023-05-30 16:31:45 +02:00
# include "../widgets/Slider.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/TextControls.h"
# include "../widgets/ObjectLists.h"
2014-07-13 20:53:37 +03:00
2018-01-05 19:21:07 +02:00
# include "../lobby/CSavingScreen.h"
2023-06-02 15:42:18 +02:00
# include "../render/Canvas.h"
2023-02-01 20:42:06 +02:00
# include "../render/CAnimation.h"
2023-02-12 17:21:16 +02:00
# include "../CMT.h"
2018-01-05 19:21:07 +02:00
2014-07-13 20:53:37 +03:00
# include "../../CCallback.h"
2023-06-07 18:51:44 +02:00
# include "../lib/mapObjectConstructors/AObjectTypeHandler.h"
# include "../lib/mapObjectConstructors/CObjectClassesHandler.h"
# include "../lib/mapObjectConstructors/CommonConstructors.h"
2017-03-17 17:48:44 +02:00
# include "../lib/mapObjects/CGHeroInstance.h"
2023-06-02 20:47:37 +02:00
# include "../lib/mapObjects/CGMarket.h"
2023-05-17 15:52:16 +02:00
# include "../lib/ArtifactUtils.h"
2023-05-24 01:05:59 +02:00
# include "../lib/mapObjects/CGTownInstance.h"
2023-06-02 20:47:37 +02:00
# include "../lib/mapObjects/ObjectTemplate.h"
2023-06-23 17:02:48 +02:00
# include "../lib/gameState/CGameState.h"
# include "../lib/gameState/InfoAboutArmy.h"
2023-06-26 16:25:29 +02:00
# include "../lib/gameState/SThievesGuildInfo.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CArtHandler.h"
# include "../lib/CBuildingHandler.h"
2014-07-13 20:53:37 +03:00
# include "../lib/CConfigHandler.h"
# include "../lib/CCreatureHandler.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CGeneralTextHandler.h"
# include "../lib/CHeroHandler.h"
2012-09-05 15:49:23 +03:00
# include "../lib/CModHandler.h"
2023-03-15 21:34:29 +02:00
# include "../lib/GameSettings.h"
2014-07-13 20:53:37 +03:00
# include "../lib/CondSh.h"
2017-08-30 12:35:23 +02:00
# include "../lib/CSkillHandler.h"
2015-02-02 10:25:26 +02:00
# include "../lib/spells/CSpellHandler.h"
2023-03-15 21:34:29 +02:00
# include "../lib/filesystem/Filesystem.h"
2014-07-13 20:53:37 +03:00
# include "../lib/CStopWatch.h"
2010-12-20 23:22:53 +02:00
# include "../lib/CTownHandler.h"
2014-07-13 20:53:37 +03:00
# include "../lib/GameConstants.h"
2023-05-01 19:29:53 +02:00
# include "../lib/bonuses/Bonus.h"
2014-01-16 23:24:06 +03:00
# include "../lib/NetPacksBase.h"
2011-12-14 00:23:17 +03:00
# include "../lib/StartInfo.h"
2023-02-12 23:52:35 +02:00
# include "../lib/TextOperations.h"
2009-05-19 21:23:04 +03:00
2018-04-07 13:34:11 +02:00
CRecruitmentWindow : : CCreatureCard : : CCreatureCard ( CRecruitmentWindow * window , const CCreature * crea , int totalAmount )
2023-06-13 18:33:35 +02:00
: CIntObject ( LCLICK | SHOW_POPUP ) ,
2015-01-18 19:23:23 +02:00
parent ( window ) ,
selected ( false ) ,
creature ( crea ) ,
amount ( totalAmount )
2009-05-19 21:23:04 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
animation = std : : make_shared < CCreaturePic > ( 1 , 1 , creature , true , true ) ;
2012-06-22 14:40:16 +03:00
// 1 + 1 px for borders
2018-04-07 13:34:11 +02:00
pos . w = animation - > pos . w + 2 ;
pos . h = animation - > pos . h + 2 ;
2012-06-22 14:40:16 +03:00
}
void CRecruitmentWindow : : CCreatureCard : : select ( bool on )
{
selected = on ;
redraw ( ) ;
}
2023-07-08 13:33:04 +02:00
void CRecruitmentWindow : : CCreatureCard : : clickPressed ( const Point & cursorPosition )
2012-06-22 14:40:16 +03:00
{
2023-07-08 13:33:04 +02:00
parent - > select ( this - > shared_from_this ( ) ) ;
2012-06-22 14:40:16 +03:00
}
2023-07-08 13:33:04 +02:00
void CRecruitmentWindow : : CCreatureCard : : showPopupWindow ( const Point & cursorPosition )
2012-06-22 14:40:16 +03:00
{
2023-06-11 17:20:10 +02:00
GH . windows ( ) . createAndPushWindow < CStackWindow > ( creature , true ) ;
2012-06-22 14:40:16 +03:00
}
2023-06-02 15:42:18 +02:00
void CRecruitmentWindow : : CCreatureCard : : showAll ( Canvas & to )
2012-06-22 14:40:16 +03:00
{
CIntObject : : showAll ( to ) ;
2018-04-07 13:34:11 +02:00
if ( selected )
2023-06-02 15:42:18 +02:00
to . drawBorder ( pos , Colors : : RED ) ;
2012-06-22 14:40:16 +03:00
else
2023-06-02 15:42:18 +02:00
to . drawBorder ( pos , Colors : : YELLOW ) ;
2012-06-22 14:40:16 +03:00
}
2018-04-07 13:34:11 +02:00
void CRecruitmentWindow : : select ( std : : shared_ptr < CCreatureCard > card )
2009-05-19 21:23:04 +03:00
{
2018-04-07 13:34:11 +02:00
if ( card = = selected )
2012-06-22 14:40:16 +03:00
return ;
2018-04-07 13:34:11 +02:00
if ( selected )
2012-06-22 14:40:16 +03:00
selected - > select ( false ) ;
selected = card ;
2018-04-07 13:34:11 +02:00
if ( selected )
2012-06-22 14:40:16 +03:00
selected - > select ( true ) ;
2018-04-07 13:34:11 +02:00
if ( card )
2012-06-22 14:40:16 +03:00
{
si32 maxAmount = card - > creature - > maxAmount ( LOCPLINT - > cb - > getResourceAmount ( ) ) ;
vstd : : amin ( maxAmount , card - > amount ) ;
slider - > setAmount ( maxAmount ) ;
2014-08-03 17:31:56 +03:00
if ( slider - > getValue ( ) ! = maxAmount )
2023-05-30 17:10:22 +02:00
slider - > scrollTo ( maxAmount ) ;
2012-06-22 14:40:16 +03:00
else // if slider already at 0 - emulate call to sliderMoved()
2012-09-30 13:35:17 +03:00
sliderMoved ( maxAmount ) ;
2012-06-22 14:40:16 +03:00
2023-04-05 02:26:29 +02:00
costPerTroopValue - > createItems ( card - > creature - > getFullRecruitCost ( ) ) ;
totalCostValue - > createItems ( card - > creature - > getFullRecruitCost ( ) ) ;
2012-06-22 14:40:16 +03:00
2023-04-05 02:26:29 +02:00
costPerTroopValue - > set ( card - > creature - > getFullRecruitCost ( ) ) ;
totalCostValue - > set ( card - > creature - > getFullRecruitCost ( ) * maxAmount ) ;
2012-06-22 14:40:16 +03:00
//Recruit %s
2023-01-02 18:00:51 +02:00
title - > setText ( boost : : str ( boost : : format ( CGI - > generaltexth - > tcommands [ 21 ] ) % card - > creature - > getNamePluralTranslated ( ) ) ) ;
2012-06-22 14:40:16 +03:00
maxButton - > block ( maxAmount = = 0 ) ;
slider - > block ( maxAmount = = 0 ) ;
}
}
void CRecruitmentWindow : : buy ( )
{
2023-04-05 02:26:29 +02:00
CreatureID crid = selected - > creature - > getId ( ) ;
2023-07-13 20:46:55 +02:00
SlotID dstslot = dst - > getSlotFor ( crid ) ;
2009-08-07 01:36:51 +03:00
2017-05-26 18:51:45 +02:00
if ( ! dstslot . validSlot ( ) & & ( selected - > creature - > warMachine = = ArtifactID : : NONE ) ) //no available slot
2009-08-07 01:36:51 +03:00
{
2023-07-13 20:46:55 +02:00
std : : pair < SlotID , SlotID > toMerge ;
bool allowMerge = CGI - > settings ( ) - > getBoolean ( EGameSettings : : DWELLINGS_ACCUMULATE_WHEN_OWNED ) ;
if ( allowMerge & & dst - > mergableStacks ( toMerge ) )
2009-08-07 01:36:51 +03:00
{
2023-07-13 20:46:55 +02:00
LOCPLINT - > cb - > mergeStacks ( dst , dst , toMerge . first , toMerge . second ) ;
2009-08-07 01:36:51 +03:00
}
else
{
2023-07-13 20:46:55 +02:00
std : : string txt ;
if ( dst - > ID = = Obj : : HERO )
{
txt = CGI - > generaltexth - > allTexts [ 425 ] ; //The %s would join your hero, but there aren't enough provisions to support them.
boost : : algorithm : : replace_first ( txt , " %s " , slider - > getValue ( ) > 1 ? CGI - > creh - > objects [ crid ] - > getNamePluralTranslated ( ) : CGI - > creh - > objects [ crid ] - > getNameSingularTranslated ( ) ) ;
}
else
{
txt = CGI - > generaltexth - > allTexts [ 17 ] ; //There is no room in the garrison for this army.
}
LOCPLINT - > showInfoDialog ( txt ) ;
return ;
2009-08-07 01:36:51 +03:00
}
}
2014-08-03 17:31:56 +03:00
onRecruit ( crid , slider - > getValue ( ) ) ;
2009-07-26 13:43:22 +03:00
if ( level > = 0 )
close ( ) ;
2009-05-19 21:23:04 +03:00
}
2023-06-02 15:42:18 +02:00
void CRecruitmentWindow : : showAll ( Canvas & to )
2009-05-19 21:23:04 +03:00
{
2012-06-15 20:08:19 +03:00
CWindowObject : : showAll ( to ) ;
2012-06-22 14:40:16 +03:00
2023-06-02 15:42:18 +02:00
Rect ( 172 , 222 , 67 , 42 ) + pos . topLeft ( ) ;
2012-06-22 14:40:16 +03:00
// recruit\total values
2023-06-02 15:42:18 +02:00
to . drawBorder ( Rect ( 172 , 222 , 67 , 42 ) + pos . topLeft ( ) , Colors : : YELLOW ) ;
to . drawBorder ( Rect ( 246 , 222 , 67 , 42 ) + pos . topLeft ( ) , Colors : : YELLOW ) ;
2012-06-22 14:40:16 +03:00
//cost boxes
2023-06-02 15:42:18 +02:00
to . drawBorder ( Rect ( 64 , 222 , 99 , 76 ) + pos . topLeft ( ) , Colors : : YELLOW ) ;
to . drawBorder ( Rect ( 322 , 222 , 99 , 76 ) + pos . topLeft ( ) , Colors : : YELLOW ) ;
2012-06-22 14:40:16 +03:00
//buttons borders
2023-06-02 15:42:18 +02:00
to . drawBorder ( Rect ( 133 , 312 , 66 , 34 ) + pos . topLeft ( ) , Colors : : METALLIC_GOLD ) ;
to . drawBorder ( Rect ( 211 , 312 , 66 , 34 ) + pos . topLeft ( ) , Colors : : METALLIC_GOLD ) ;
to . drawBorder ( Rect ( 289 , 312 , 66 , 34 ) + pos . topLeft ( ) , Colors : : METALLIC_GOLD ) ;
2009-05-19 21:23:04 +03:00
}
2018-04-07 13:34:11 +02:00
CRecruitmentWindow : : CRecruitmentWindow ( const CGDwelling * Dwelling , int Level , const CArmedInstance * Dst , const std : : function < void ( CreatureID , int ) > & Recruit , int y_offset ) :
2018-10-29 15:12:07 +02:00
CStatusbarWindow ( PLAYER_COLORED , " TPRCRT " ) ,
2012-06-22 14:40:16 +03:00
onRecruit ( Recruit ) ,
2015-01-18 19:23:23 +02:00
level ( Level ) ,
dst ( Dst ) ,
selected ( nullptr ) ,
dwelling ( Dwelling )
2009-05-19 21:23:04 +03:00
{
2012-06-22 14:40:16 +03:00
moveBy ( Point ( 0 , y_offset ) ) ;
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2011-02-12 18:12:48 +02:00
2022-11-29 17:07:21 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2009-07-26 13:43:22 +03:00
2023-06-22 22:49:38 +02:00
slider = std : : make_shared < CSlider > ( Point ( 176 , 279 ) , 135 , std : : bind ( & CRecruitmentWindow : : sliderMoved , this , _1 ) , 0 , 0 , 0 , Orientation : : HORIZONTAL ) ;
2009-07-26 13:43:22 +03:00
2023-05-30 17:10:22 +02:00
maxButton = std : : make_shared < CButton > ( Point ( 134 , 313 ) , " IRCBTNS.DEF " , CGI - > generaltexth - > zelp [ 553 ] , std : : bind ( & CSlider : : scrollToMax , slider ) , EShortcut : : RECRUITMENT_MAX ) ;
2023-04-28 13:22:03 +02:00
buyButton = std : : make_shared < CButton > ( Point ( 212 , 313 ) , " IBY6432.DEF " , CGI - > generaltexth - > zelp [ 554 ] , std : : bind ( & CRecruitmentWindow : : buy , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2023-04-27 19:21:06 +02:00
cancelButton = std : : make_shared < CButton > ( Point ( 290 , 313 ) , " ICN6432.DEF " , CGI - > generaltexth - > zelp [ 555 ] , std : : bind ( & CRecruitmentWindow : : close , this ) , EShortcut : : GLOBAL_CANCEL ) ;
2012-06-16 13:41:14 +03:00
2022-11-26 23:12:20 +02:00
title = std : : make_shared < CLabel > ( 243 , 32 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW ) ;
availableValue = std : : make_shared < CLabel > ( 205 , 253 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
toRecruitValue = std : : make_shared < CLabel > ( 279 , 253 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2012-06-15 20:08:19 +03:00
2018-04-07 13:34:11 +02:00
costPerTroopValue = std : : make_shared < CreatureCostBox > ( Rect ( 65 , 222 , 97 , 74 ) , CGI - > generaltexth - > allTexts [ 346 ] ) ;
totalCostValue = std : : make_shared < CreatureCostBox > ( Rect ( 323 , 222 , 97 , 74 ) , CGI - > generaltexth - > allTexts [ 466 ] ) ;
2022-11-26 23:12:20 +02:00
availableTitle = std : : make_shared < CLabel > ( 205 , 233 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 465 ] ) ;
toRecruitTitle = std : : make_shared < CLabel > ( 279 , 233 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 16 ] ) ;
2009-05-19 21:23:04 +03:00
2012-06-22 14:40:16 +03:00
availableCreaturesChanged ( ) ;
2009-05-19 21:23:04 +03:00
}
2012-06-22 14:40:16 +03:00
void CRecruitmentWindow : : availableCreaturesChanged ( )
2009-07-26 13:43:22 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2012-06-22 14:40:16 +03:00
2012-06-27 23:44:01 +03:00
size_t selectedIndex = 0 ;
2018-04-07 13:34:11 +02:00
if ( ! cards . empty ( ) & & selected ) // find position of selected item
2012-06-27 23:44:01 +03:00
selectedIndex = std : : find ( cards . begin ( ) , cards . end ( ) , selected ) - cards . begin ( ) ;
2012-06-22 14:40:16 +03:00
select ( nullptr ) ;
cards . clear ( ) ;
2011-02-12 18:12:48 +02:00
2009-07-26 13:43:22 +03:00
for ( int i = 0 ; i < dwelling - > creatures . size ( ) ; i + + )
{
2012-06-22 14:40:16 +03:00
//find appropriate level
2012-01-12 18:23:00 +03:00
if ( level > = 0 & & i ! = level )
2009-07-26 13:43:22 +03:00
continue ;
2012-06-22 14:40:16 +03:00
int amount = dwelling - > creatures [ i ] . first ;
2009-07-26 13:43:22 +03:00
2012-06-22 14:40:16 +03:00
//create new cards
2013-06-29 16:05:48 +03:00
for ( auto & creature : boost : : adaptors : : reverse ( dwelling - > creatures [ i ] . second ) )
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
cards . push_back ( std : : make_shared < CCreatureCard > ( this , CGI - > creh - > objects [ creature ] , amount ) ) ;
2012-06-22 14:40:16 +03:00
}
2009-07-26 13:43:22 +03:00
2012-06-27 23:44:01 +03:00
const int creatureWidth = 102 ;
//normal distance between cards - 18px
int requiredSpace = 18 ;
//maximum distance we can use without reaching window borders
2020-10-01 10:38:06 +02:00
int availableSpace = pos . w - 50 - creatureWidth * ( int ) cards . size ( ) ;
2012-06-27 23:44:01 +03:00
if ( cards . size ( ) > 1 ) // avoid division by zero
2020-10-01 10:38:06 +02:00
availableSpace / = ( int ) cards . size ( ) - 1 ;
2012-06-27 23:44:01 +03:00
else
availableSpace = 0 ;
assert ( availableSpace > = 0 ) ;
const int spaceBetween = std : : min ( requiredSpace , availableSpace ) ;
const int totalCreatureWidth = spaceBetween + creatureWidth ;
2012-06-22 14:40:16 +03:00
//now we know total amount of cards and can move them to correct position
2020-10-01 10:38:06 +02:00
int curx = pos . w / 2 - ( creatureWidth * ( int ) cards . size ( ) / 2 ) - ( spaceBetween * ( ( int ) cards . size ( ) - 1 ) / 2 ) ;
2013-06-29 16:05:48 +03:00
for ( auto & card : cards )
2012-06-22 14:40:16 +03:00
{
card - > moveBy ( Point ( curx , 64 ) ) ;
2012-06-27 23:44:01 +03:00
curx + = totalCreatureWidth ;
2009-07-26 13:43:22 +03:00
}
2012-06-27 23:44:01 +03:00
//restore selection
select ( cards [ selectedIndex ] ) ;
2012-06-22 14:40:16 +03:00
2014-08-03 17:31:56 +03:00
if ( slider - > getValue ( ) = = slider - > getAmount ( ) )
2023-05-30 17:10:22 +02:00
slider - > scrollToMax ( ) ;
2012-06-22 14:40:16 +03:00
else // if slider already at 0 - emulate call to sliderMoved()
2014-08-03 17:31:56 +03:00
sliderMoved ( slider - > getAmount ( ) ) ;
2012-06-22 14:40:16 +03:00
}
void CRecruitmentWindow : : sliderMoved ( int to )
{
2018-04-07 13:34:11 +02:00
if ( ! selected )
2012-06-22 14:40:16 +03:00
return ;
buyButton - > block ( ! to ) ;
2023-03-09 15:36:46 +02:00
availableValue - > setText ( std : : to_string ( selected - > amount - to ) ) ;
toRecruitValue - > setText ( std : : to_string ( to ) ) ;
2012-06-22 14:40:16 +03:00
2023-04-05 02:26:29 +02:00
totalCostValue - > set ( selected - > creature - > getFullRecruitCost ( ) * to ) ;
2009-07-26 13:43:22 +03:00
}
2018-04-07 13:34:11 +02:00
CSplitWindow : : CSplitWindow ( const CCreature * creature , std : : function < void ( int , int ) > callback_ , int leftMin_ , int rightMin_ , int leftAmount_ , int rightAmount_ )
: CWindowObject ( PLAYER_COLORED , " GPUCRDIV " ) ,
2015-01-18 19:23:23 +02:00
callback ( callback_ ) ,
leftAmount ( leftAmount_ ) ,
rightAmount ( rightAmount_ ) ,
leftMin ( leftMin_ ) ,
2018-04-07 13:34:11 +02:00
rightMin ( rightMin_ )
2009-05-19 21:23:04 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2010-02-02 18:24:53 +02:00
2012-06-13 16:04:06 +03:00
int total = leftAmount + rightAmount ;
int leftMax = total - rightMin ;
int rightMax = total - leftMin ;
2009-05-19 21:23:04 +03:00
2023-04-28 13:22:03 +02:00
ok = std : : make_shared < CButton > ( Point ( 20 , 263 ) , " IOK6432 " , CButton : : tooltip ( ) , std : : bind ( & CSplitWindow : : apply , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2023-04-27 19:21:06 +02:00
cancel = std : : make_shared < CButton > ( Point ( 214 , 263 ) , " ICN6432 " , CButton : : tooltip ( ) , std : : bind ( & CSplitWindow : : close , this ) , EShortcut : : GLOBAL_CANCEL ) ;
2009-05-19 21:23:04 +03:00
2018-04-07 13:34:11 +02:00
int sliderPosition = total - leftMin - rightMin ;
2009-05-19 21:23:04 +03:00
2018-04-07 13:34:11 +02:00
leftInput = std : : make_shared < CTextInput > ( Rect ( 20 , 218 , 100 , 36 ) , FONT_BIG , std : : bind ( & CSplitWindow : : setAmountText , this , _1 , true ) ) ;
rightInput = std : : make_shared < CTextInput > ( Rect ( 176 , 218 , 100 , 36 ) , FONT_BIG , std : : bind ( & CSplitWindow : : setAmountText , this , _1 , false ) ) ;
2009-05-19 21:23:04 +03:00
2012-06-13 16:04:06 +03:00
//add filters to allow only number input
2014-11-12 22:45:48 +02:00
leftInput - > filters + = std : : bind ( & CTextInput : : numberFilter , _1 , _2 , leftMin , leftMax ) ;
rightInput - > filters + = std : : bind ( & CTextInput : : numberFilter , _1 , _2 , rightMin , rightMax ) ;
2009-05-19 21:23:04 +03:00
2023-03-09 15:36:46 +02:00
leftInput - > setText ( std : : to_string ( leftAmount ) , false ) ;
rightInput - > setText ( std : : to_string ( rightAmount ) , false ) ;
2009-05-19 21:23:04 +03:00
2018-04-07 13:34:11 +02:00
animLeft = std : : make_shared < CCreaturePic > ( 20 , 54 , creature , true , false ) ;
animRight = std : : make_shared < CCreaturePic > ( 177 , 54 , creature , true , false ) ;
2009-05-19 21:23:04 +03:00
2023-06-22 22:49:38 +02:00
slider = std : : make_shared < CSlider > ( Point ( 21 , 194 ) , 257 , std : : bind ( & CSplitWindow : : sliderMoved , this , _1 ) , 0 , sliderPosition , rightAmount - rightMin , Orientation : : HORIZONTAL ) ;
2009-09-07 05:29:44 +03:00
2018-04-07 13:34:11 +02:00
std : : string titleStr = CGI - > generaltexth - > allTexts [ 256 ] ;
2023-01-02 18:00:51 +02:00
boost : : algorithm : : replace_first ( titleStr , " %s " , creature - > getNamePluralTranslated ( ) ) ;
2022-11-26 23:12:20 +02:00
title = std : : make_shared < CLabel > ( 150 , 34 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , titleStr ) ;
2012-06-13 16:04:06 +03:00
}
2009-05-19 21:23:04 +03:00
2012-06-13 16:04:06 +03:00
void CSplitWindow : : setAmountText ( std : : string text , bool left )
{
2014-12-23 06:38:58 +02:00
int amount = 0 ;
2018-04-07 13:34:11 +02:00
if ( text . length ( ) )
2009-05-19 21:23:04 +03:00
{
2014-12-23 06:38:58 +02:00
try
{
amount = boost : : lexical_cast < int > ( text ) ;
}
catch ( boost : : bad_lexical_cast & )
{
amount = left ? leftAmount : rightAmount ;
}
int total = leftAmount + rightAmount ;
2018-04-07 13:34:11 +02:00
if ( amount > total )
2014-12-23 06:38:58 +02:00
amount = total ;
2009-05-19 21:23:04 +03:00
}
2014-12-23 06:38:58 +02:00
setAmount ( amount , left ) ;
2023-05-30 17:10:22 +02:00
slider - > scrollTo ( rightAmount - rightMin ) ;
2009-05-19 21:23:04 +03:00
}
2012-06-13 16:04:06 +03:00
void CSplitWindow : : setAmount ( int value , bool left )
2009-05-19 21:23:04 +03:00
{
2012-06-13 16:04:06 +03:00
int total = leftAmount + rightAmount ;
leftAmount = left ? value : total - value ;
rightAmount = left ? total - value : value ;
2023-03-09 15:36:46 +02:00
leftInput - > setText ( std : : to_string ( leftAmount ) ) ;
rightInput - > setText ( std : : to_string ( rightAmount ) ) ;
2012-06-13 16:04:06 +03:00
}
void CSplitWindow : : apply ( )
{
callback ( leftAmount , rightAmount ) ;
close ( ) ;
}
void CSplitWindow : : sliderMoved ( int to )
{
setAmount ( rightMin + to , false ) ;
2009-05-19 21:23:04 +03:00
}
2018-04-07 13:34:11 +02:00
CLevelWindow : : CLevelWindow ( const CGHeroInstance * hero , PrimarySkill : : PrimarySkill pskill , std : : vector < SecondarySkill > & skills , std : : function < void ( ui32 ) > callback )
: CWindowObject ( PLAYER_COLORED , " LVLUPBKG " ) ,
2015-01-18 19:23:23 +02:00
cb ( callback )
2009-05-19 21:23:04 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2009-05-19 21:23:04 +03:00
LOCPLINT - > showingDialog - > setn ( true ) ;
2012-06-15 20:08:19 +03:00
2018-04-07 13:34:11 +02:00
if ( ! skills . empty ( ) )
{
std : : vector < std : : shared_ptr < CSelectableComponent > > comps ;
for ( auto & skill : skills )
{
auto comp = std : : make_shared < CSelectableComponent > ( CComponent : : secskill , skill , hero - > getSecSkillLevel ( SecondarySkill ( skill ) ) + 1 , CComponent : : medium ) ;
comps . push_back ( comp ) ;
}
2012-06-15 20:08:19 +03:00
2018-04-07 13:34:11 +02:00
box = std : : make_shared < CComponentBox > ( comps , Rect ( 75 , 300 , pos . w - 150 , 100 ) ) ;
}
2009-05-19 21:23:04 +03:00
2018-04-07 13:34:11 +02:00
portrait = std : : make_shared < CAnimImage > ( " PortraitsLarge " , hero - > portrait , 0 , 170 , 66 ) ;
2023-04-28 13:22:03 +02:00
ok = std : : make_shared < CButton > ( Point ( 297 , 413 ) , " IOKAY " , CButton : : tooltip ( ) , std : : bind ( & CLevelWindow : : close , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2009-05-19 21:23:04 +03:00
2018-04-07 13:34:11 +02:00
//%s has gained a level.
2023-01-02 13:27:03 +02:00
mainTitle = std : : make_shared < CLabel > ( 192 , 33 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 444 ] ) % hero - > getNameTranslated ( ) ) ) ;
2009-05-19 21:23:04 +03:00
2018-04-07 13:34:11 +02:00
//%s is now a level %d %s.
2023-02-25 17:44:15 +02:00
std : : string levelTitleText = CGI - > generaltexth - > translate ( " core.genrltxt.445 " ) ;
boost : : replace_first ( levelTitleText , " %s " , hero - > getNameTranslated ( ) ) ;
boost : : replace_first ( levelTitleText , " %d " , std : : to_string ( hero - > level ) ) ;
boost : : replace_first ( levelTitleText , " %s " , hero - > type - > heroClass - > getNameTranslated ( ) ) ;
levelTitle = std : : make_shared < CLabel > ( 192 , 162 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , levelTitleText ) ;
2010-02-02 18:24:53 +02:00
2018-04-07 13:34:11 +02:00
skillIcon = std : : make_shared < CAnimImage > ( " PSKIL42 " , pskill , 0 , 174 , 190 ) ;
2012-07-07 16:32:37 +03:00
2022-11-26 23:12:20 +02:00
skillValue = std : : make_shared < CLabel > ( 192 , 253 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > primarySkillNames [ pskill ] + " +1 " ) ;
2009-05-19 21:23:04 +03:00
}
2012-06-15 20:08:19 +03:00
2018-04-07 13:34:11 +02:00
2009-05-19 21:23:04 +03:00
CLevelWindow : : ~ CLevelWindow ( )
{
2012-07-07 16:32:37 +03:00
//FIXME: call callback if there was nothing to select?
if ( box & & box - > selectedIndex ( ) ! = - 1 )
cb ( box - > selectedIndex ( ) ) ;
2012-06-15 20:08:19 +03:00
LOCPLINT - > showingDialog - > setn ( false ) ;
2009-05-19 21:23:04 +03:00
}
2018-04-07 13:34:11 +02:00
CTavernWindow : : CTavernWindow ( const CGObjectInstance * TavernObj )
2018-10-29 15:12:07 +02:00
: CStatusbarWindow ( PLAYER_COLORED , " TPTAVERN " ) ,
2012-06-15 20:08:19 +03:00
tavernObj ( TavernObj )
2009-05-19 21:23:04 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2010-07-09 02:03:27 +03:00
std : : vector < const CGHeroInstance * > h = LOCPLINT - > cb - > getAvailableHeroes ( TavernObj ) ;
2014-03-01 16:42:23 +03:00
if ( h . size ( ) < 2 )
h . resize ( 2 , nullptr ) ;
2010-07-09 02:03:27 +03:00
2013-03-14 23:44:00 +03:00
selected = 0 ;
2018-04-07 13:34:11 +02:00
if ( ! h [ 0 ] )
2013-03-14 23:44:00 +03:00
selected = 1 ;
2018-04-07 13:34:11 +02:00
if ( ! h [ 0 ] & & ! h [ 1 ] )
2009-05-19 21:23:04 +03:00
selected = - 1 ;
2018-04-07 13:34:11 +02:00
2009-05-30 19:17:44 +03:00
oldSelected = - 1 ;
2010-02-02 18:24:53 +02:00
2018-04-07 13:34:11 +02:00
h1 = std : : make_shared < HeroPortrait > ( selected , 0 , 72 , 299 , h [ 0 ] ) ;
h2 = std : : make_shared < HeroPortrait > ( selected , 1 , 162 , 299 , h [ 1 ] ) ;
2023-06-02 15:42:18 +02:00
title = std : : make_shared < CLabel > ( 197 , 32 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > jktexts [ 37 ] ) ;
2023-03-09 15:36:46 +02:00
cost = std : : make_shared < CLabel > ( 320 , 328 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , std : : to_string ( GameConstants : : HERO_GOLD_COST ) ) ;
2023-06-02 15:42:18 +02:00
heroDescription = std : : make_shared < CTextBox > ( " " , Rect ( 30 , 373 , 233 , 35 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
heroesForHire = std : : make_shared < CLabel > ( 145 , 283 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > jktexts [ 38 ] ) ;
2015-11-30 16:51:28 +02:00
auto rumorText = boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 216 ] ) % LOCPLINT - > cb - > getTavernRumor ( tavernObj ) ) ;
2023-06-02 15:42:18 +02:00
rumor = std : : make_shared < CTextBox > ( rumorText , Rect ( 32 , 188 , 330 , 66 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2010-07-09 02:03:27 +03:00
2022-11-29 17:07:21 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2023-04-27 19:21:06 +02:00
cancel = std : : make_shared < CButton > ( Point ( 310 , 428 ) , " ICANCEL.DEF " , CButton : : tooltip ( CGI - > generaltexth - > tavernInfo [ 7 ] ) , std : : bind ( & CTavernWindow : : close , this ) , EShortcut : : GLOBAL_CANCEL ) ;
2023-04-28 13:22:03 +02:00
recruit = std : : make_shared < CButton > ( Point ( 272 , 355 ) , " TPTAV01.DEF " , CButton : : tooltip ( ) , std : : bind ( & CTavernWindow : : recruitb , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2023-04-27 19:21:06 +02:00
thiefGuild = std : : make_shared < CButton > ( Point ( 22 , 428 ) , " TPTAV02.DEF " , CButton : : tooltip ( CGI - > generaltexth - > tavernInfo [ 5 ] ) , std : : bind ( & CTavernWindow : : thievesguildb , this ) , EShortcut : : ADVENTURE_THIEVES_GUILD ) ;
2009-05-19 21:23:04 +03:00
2023-04-05 02:26:29 +02:00
if ( LOCPLINT - > cb - > getResourceAmount ( EGameResID : : GOLD ) < GameConstants : : HERO_GOLD_COST ) //not enough gold
2009-05-19 21:23:04 +03:00
{
2014-08-03 14:16:19 +03:00
recruit - > addHoverText ( CButton : : NORMAL , CGI - > generaltexth - > tavernInfo [ 0 ] ) ; //Cannot afford a Hero
2013-03-14 23:44:00 +03:00
recruit - > block ( true ) ;
2009-05-19 21:23:04 +03:00
}
2023-03-15 23:47:26 +02:00
else if ( LOCPLINT - > cb - > howManyHeroes ( true ) > = CGI - > settings ( ) - > getInteger ( EGameSettings : : HEROES_PER_PLAYER_TOTAL_CAP ) )
2009-05-19 21:23:04 +03:00
{
2014-08-03 14:16:19 +03:00
//Cannot recruit. You already have %d Heroes.
recruit - > addHoverText ( CButton : : NORMAL , boost : : str ( boost : : format ( CGI - > generaltexth - > tavernInfo [ 1 ] ) % LOCPLINT - > cb - > howManyHeroes ( true ) ) ) ;
2014-07-13 18:39:45 +03:00
recruit - > block ( true ) ;
2009-05-19 21:23:04 +03:00
}
2023-03-15 23:47:26 +02:00
else if ( LOCPLINT - > cb - > howManyHeroes ( false ) > = CGI - > settings ( ) - > getInteger ( EGameSettings : : HEROES_PER_PLAYER_ON_MAP_CAP ) )
2009-05-19 21:23:04 +03:00
{
2014-08-03 14:16:19 +03:00
//Cannot recruit. You already have %d Heroes.
recruit - > addHoverText ( CButton : : NORMAL , boost : : str ( boost : : format ( CGI - > generaltexth - > tavernInfo [ 1 ] ) % LOCPLINT - > cb - > howManyHeroes ( false ) ) ) ;
2014-07-13 18:39:45 +03:00
recruit - > block ( true ) ;
2009-05-19 21:23:04 +03:00
}
2014-07-13 18:39:45 +03:00
else if ( LOCPLINT - > castleInt & & LOCPLINT - > castleInt - > town - > visitingHero )
2009-05-19 21:23:04 +03:00
{
2014-08-03 14:16:19 +03:00
recruit - > addHoverText ( CButton : : NORMAL , CGI - > generaltexth - > tavernInfo [ 2 ] ) ; //Cannot recruit. You already have a Hero in this town.
2014-07-13 18:39:45 +03:00
recruit - > block ( true ) ;
2009-05-19 21:23:04 +03:00
}
2014-07-13 18:39:45 +03:00
else
2009-05-19 21:23:04 +03:00
{
2014-07-13 18:39:45 +03:00
if ( selected = = - 1 )
recruit - > block ( true ) ;
2009-05-19 21:23:04 +03:00
}
2018-04-07 13:34:11 +02:00
if ( LOCPLINT - > castleInt )
2014-07-13 18:39:45 +03:00
CCS - > videoh - > open ( LOCPLINT - > castleInt - > town - > town - > clientInfo . tavernVideo ) ;
else
CCS - > videoh - > open ( " TAVERN.BIK " ) ;
2009-05-19 21:23:04 +03:00
}
2014-07-13 18:39:45 +03:00
void CTavernWindow : : recruitb ( )
2009-05-19 21:23:04 +03:00
{
2014-07-13 18:39:45 +03:00
const CGHeroInstance * toBuy = ( selected ? h2 : h1 ) - > h ;
const CGObjectInstance * obj = tavernObj ;
close ( ) ;
LOCPLINT - > cb - > recruitHero ( obj , toBuy ) ;
2009-05-19 21:23:04 +03:00
}
2014-07-13 18:39:45 +03:00
void CTavernWindow : : thievesguildb ( )
2009-06-18 18:05:00 +03:00
{
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CThievesGuildWindow > ( tavernObj ) ;
2009-06-18 18:05:00 +03:00
}
2014-07-13 18:39:45 +03:00
CTavernWindow : : ~ CTavernWindow ( )
2010-12-17 00:32:53 +02:00
{
2014-07-13 18:39:45 +03:00
CCS - > videoh - > close ( ) ;
2010-12-17 00:32:53 +02:00
}
2023-06-02 15:42:18 +02:00
void CTavernWindow : : show ( Canvas & to )
2011-03-12 23:55:31 +02:00
{
2014-07-13 18:39:45 +03:00
CWindowObject : : show ( to ) ;
2011-03-12 23:55:31 +02:00
2014-07-13 18:39:45 +03:00
if ( selected > = 0 )
2011-03-12 23:55:31 +02:00
{
2018-04-07 13:34:11 +02:00
auto sel = selected ? h2 : h1 ;
2014-07-13 18:39:45 +03:00
2023-06-02 15:42:18 +02:00
if ( selected ! = oldSelected )
2011-03-12 23:55:31 +02:00
{
2014-07-13 18:39:45 +03:00
// Selected hero just changed. Update RECRUIT button hover text if recruitment is allowed.
oldSelected = selected ;
2023-06-02 15:42:18 +02:00
heroDescription - > setText ( sel - > description ) ;
2014-08-03 14:16:19 +03:00
//Recruit %s the %s
2023-06-02 15:42:18 +02:00
if ( ! recruit - > isBlocked ( ) )
recruit - > addHoverText ( CButton : : NORMAL , boost : : str ( boost : : format ( CGI - > generaltexth - > tavernInfo [ 3 ] ) % sel - > h - > getNameTranslated ( ) % sel - > h - > type - > heroClass - > getNameTranslated ( ) ) ) ;
2011-03-12 23:55:31 +02:00
}
2023-06-02 15:42:18 +02:00
to . drawBorder ( Rect : : createAround ( sel - > pos , 2 ) , Colors : : BRIGHT_YELLOW , 2 ) ;
2014-07-13 18:39:45 +03:00
}
2023-06-02 15:42:18 +02:00
CCS - > videoh - > update ( pos . x + 70 , pos . y + 56 , to . getInternalSurface ( ) , true , false ) ;
2011-03-12 23:55:31 +02:00
}
2023-07-09 16:48:25 +02:00
void CTavernWindow : : HeroPortrait : : clickPressed ( const Point & cursorPosition )
2010-07-22 03:32:45 +03:00
{
2023-07-08 13:33:04 +02:00
if ( h )
2014-07-13 18:39:45 +03:00
* _sel = _id ;
2010-07-22 03:32:45 +03:00
}
2023-07-08 13:33:04 +02:00
void CTavernWindow : : HeroPortrait : : showPopupWindow ( const Point & cursorPosition )
2010-02-04 17:50:59 +02:00
{
2023-06-11 17:20:10 +02:00
if ( h )
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CRClickPopupInt > ( std : : make_shared < CHeroWindow > ( h ) ) ;
2010-02-04 17:50:59 +02:00
}
2018-04-07 13:34:11 +02:00
CTavernWindow : : HeroPortrait : : HeroPortrait ( int & sel , int id , int x , int y , const CGHeroInstance * H )
2023-06-13 18:33:35 +02:00
: CIntObject ( LCLICK | SHOW_POPUP | HOVER ) ,
2018-04-07 13:34:11 +02:00
h ( H ) , _sel ( & sel ) , _id ( id )
2010-02-04 17:50:59 +02:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:39:45 +03:00
h = H ;
pos . x + = x ;
pos . y + = y ;
pos . w = 58 ;
pos . h = 64 ;
2010-02-04 17:50:59 +02:00
2014-07-13 18:39:45 +03:00
if ( H )
{
hoverName = CGI - > generaltexth - > tavernInfo [ 4 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( hoverName , " %s " , H - > getNameTranslated ( ) ) ;
2010-07-22 03:32:45 +03:00
2020-10-01 10:38:06 +02:00
int artifs = ( int ) h - > artifactsWorn . size ( ) + ( int ) h - > artifactsInBackpack . size ( ) ;
2014-07-13 18:39:45 +03:00
for ( int i = 13 ; i < = 17 ; i + + ) //war machines and spellbook don't count
if ( vstd : : contains ( h - > artifactsWorn , ArtifactPosition ( i ) ) )
artifs - - ;
2010-02-04 17:50:59 +02:00
2014-07-13 18:39:45 +03:00
description = CGI - > generaltexth - > allTexts [ 215 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( description , " %s " , h - > getNameTranslated ( ) ) ;
2023-03-09 15:36:46 +02:00
boost : : algorithm : : replace_first ( description , " %d " , std : : to_string ( h - > level ) ) ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( description , " %s " , h - > type - > heroClass - > getNameTranslated ( ) ) ;
2023-03-09 15:36:46 +02:00
boost : : algorithm : : replace_first ( description , " %d " , std : : to_string ( artifs ) ) ;
2014-07-13 18:39:45 +03:00
2018-04-07 13:34:11 +02:00
portrait = std : : make_shared < CAnimImage > ( " portraitsLarge " , h - > portrait ) ;
2014-07-13 18:39:45 +03:00
}
2010-02-04 17:50:59 +02:00
}
2018-04-07 13:34:11 +02:00
void CTavernWindow : : HeroPortrait : : hover ( bool on )
2010-12-17 00:32:53 +02:00
{
2014-07-13 18:39:45 +03:00
//Hoverable::hover(on);
if ( on )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( hoverName ) ;
2014-07-13 18:39:45 +03:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2010-12-17 00:32:53 +02:00
}
2021-11-28 21:48:22 +02:00
static const std : : string QUICK_EXCHANGE_MOD_PREFIX = " quick-exchange " ;
static const std : : string QUICK_EXCHANGE_BG = QUICK_EXCHANGE_MOD_PREFIX + " /TRADEQE " ;
2020-03-31 22:50:32 +02:00
2021-11-28 21:48:22 +02:00
static bool isQuickExchangeLayoutAvailable ( )
2020-03-31 22:50:32 +02:00
{
2021-11-28 21:48:22 +02:00
return CResourceHandler : : get ( ) - > existsResource ( ResourceID ( std : : string ( " SPRITES/ " ) + QUICK_EXCHANGE_BG , EResType : : IMAGE ) ) ;
2021-02-11 21:06:47 +02:00
}
2021-02-14 17:11:46 +02:00
// Runs a task asynchronously with gamestate locking and waitTillRealize set to true
2021-02-13 22:30:50 +02:00
class GsThread
{
private :
2021-02-14 17:11:46 +02:00
std : : function < void ( ) > action ;
std : : shared_ptr < CCallback > cb ;
public :
static void run ( std : : function < void ( ) > action )
2021-02-13 22:30:50 +02:00
{
2021-02-14 17:11:46 +02:00
std : : shared_ptr < GsThread > instance ( new GsThread ( action ) ) ;
2021-02-13 22:30:50 +02:00
2021-02-14 17:11:46 +02:00
boost : : thread ( std : : bind ( & GsThread : : staticRun , instance ) ) ;
}
private :
2021-02-13 22:30:50 +02:00
GsThread ( std : : function < void ( ) > action )
2021-02-14 17:11:46 +02:00
: action ( action ) , cb ( LOCPLINT - > cb )
2021-02-13 22:30:50 +02:00
{
}
2021-02-14 17:11:46 +02:00
static void staticRun ( std : : shared_ptr < GsThread > instance )
{
instance - > run ( ) ;
}
void run ( )
2021-02-13 22:30:50 +02:00
{
boost : : shared_lock < boost : : shared_mutex > gsLock ( CGameState : : mutex ) ;
2021-02-14 17:11:46 +02:00
auto originalWaitTillRealize = cb - > waitTillRealize ;
auto originalUnlockGsWhenWating = cb - > unlockGsWhenWaiting ;
2021-02-13 22:30:50 +02:00
2021-02-14 17:11:46 +02:00
cb - > waitTillRealize = true ;
cb - > unlockGsWhenWaiting = true ;
2021-02-13 22:30:50 +02:00
2021-02-14 17:11:46 +02:00
action ( ) ;
2021-02-13 22:30:50 +02:00
2021-02-14 17:11:46 +02:00
cb - > waitTillRealize = originalWaitTillRealize ;
cb - > unlockGsWhenWaiting = originalUnlockGsWhenWating ;
2021-02-13 22:30:50 +02:00
}
} ;
CExchangeController : : CExchangeController ( CExchangeWindow * view , ObjectInstanceID hero1 , ObjectInstanceID hero2 )
: left ( LOCPLINT - > cb - > getHero ( hero1 ) ) , right ( LOCPLINT - > cb - > getHero ( hero2 ) ) , cb ( LOCPLINT - > cb ) , view ( view )
2021-02-11 21:06:47 +02:00
{
}
std : : function < void ( ) > CExchangeController : : onMoveArmyToLeft ( )
{
2021-02-13 22:30:50 +02:00
return [ & ] ( ) { moveArmy ( false ) ; } ;
2021-02-11 21:06:47 +02:00
}
std : : function < void ( ) > CExchangeController : : onMoveArmyToRight ( )
{
2021-02-13 22:30:50 +02:00
return [ & ] ( ) { moveArmy ( true ) ; } ;
2021-02-11 21:06:47 +02:00
}
2021-02-13 22:30:50 +02:00
std : : vector < CArtifactInstance * > getBackpackArts ( const CGHeroInstance * hero )
{
std : : vector < CArtifactInstance * > result ;
2021-02-11 21:06:47 +02:00
2021-02-13 22:30:50 +02:00
for ( auto slot : hero - > artifactsInBackpack )
{
result . push_back ( slot . artifact ) ;
}
return result ;
}
2021-02-14 17:11:46 +02:00
std : : function < void ( ) > CExchangeController : : onSwapArtifacts ( )
{
return [ & ] ( )
{
GsThread : : run ( [ = ]
{
2022-11-10 23:24:41 +02:00
cb - > bulkMoveArtifacts ( left - > id , right - > id , true ) ;
2021-02-11 21:06:47 +02:00
} ) ;
2021-02-13 22:30:50 +02:00
} ;
}
2021-02-11 21:06:47 +02:00
2021-02-13 22:30:50 +02:00
std : : function < void ( ) > CExchangeController : : onMoveArtifactsToLeft ( )
{
return [ & ] ( ) { moveArtifacts ( false ) ; } ;
}
2021-02-11 21:06:47 +02:00
2021-02-13 22:30:50 +02:00
std : : function < void ( ) > CExchangeController : : onMoveArtifactsToRight ( )
{
return [ & ] ( ) { moveArtifacts ( true ) ; } ;
}
2021-02-11 21:06:47 +02:00
2021-02-13 22:30:50 +02:00
std : : vector < std : : pair < SlotID , CStackInstance * > > getStacks ( const CArmedInstance * source )
{
auto slots = source - > Slots ( ) ;
return std : : vector < std : : pair < SlotID , CStackInstance * > > ( slots . begin ( ) , slots . end ( ) ) ;
}
std : : function < void ( ) > CExchangeController : : onSwapArmy ( )
{
return [ & ] ( )
{
2021-02-14 17:11:46 +02:00
GsThread : : run ( [ = ]
2021-02-11 21:06:47 +02:00
{
2022-12-07 18:13:54 +02:00
if ( left - > tempOwner ! = cb - > getMyColor ( )
2021-11-28 21:48:22 +02:00
| | right - > tempOwner ! = cb - > getMyColor ( ) )
{
return ;
}
2021-02-13 22:30:50 +02:00
auto leftSlots = getStacks ( left ) ;
auto rightSlots = getStacks ( right ) ;
2021-02-11 21:06:47 +02:00
2021-02-13 22:30:50 +02:00
auto i = leftSlots . begin ( ) , j = rightSlots . begin ( ) ;
2021-02-11 21:06:47 +02:00
2021-02-13 22:30:50 +02:00
for ( ; i ! = leftSlots . end ( ) & & j ! = rightSlots . end ( ) ; i + + , j + + )
2021-02-11 21:06:47 +02:00
{
2021-02-13 22:30:50 +02:00
cb - > swapCreatures ( left , right , i - > first , j - > first ) ;
}
if ( i ! = leftSlots . end ( ) )
{
for ( ; i ! = leftSlots . end ( ) ; i + + )
2021-02-11 21:06:47 +02:00
{
2021-02-13 22:30:50 +02:00
cb - > swapCreatures ( left , right , i - > first , right - > getFreeSlot ( ) ) ;
2021-02-11 21:06:47 +02:00
}
2021-02-13 22:30:50 +02:00
}
else if ( j ! = rightSlots . end ( ) )
{
for ( ; j ! = rightSlots . end ( ) ; j + + )
2021-02-11 21:06:47 +02:00
{
2021-02-13 22:30:50 +02:00
cb - > swapCreatures ( left , right , left - > getFreeSlot ( ) , j - > first ) ;
2021-02-11 21:06:47 +02:00
}
}
2021-02-13 22:30:50 +02:00
} ) ;
} ;
}
2021-11-28 21:48:22 +02:00
std : : function < void ( ) > CExchangeController : : onMoveStackToLeft ( SlotID slotID )
{
return [ = ] ( )
{
if ( right - > tempOwner ! = cb - > getMyColor ( ) )
{
return ;
}
moveStack ( right , left , slotID ) ;
} ;
}
std : : function < void ( ) > CExchangeController : : onMoveStackToRight ( SlotID slotID )
{
return [ = ] ( )
{
if ( left - > tempOwner ! = cb - > getMyColor ( ) )
{
return ;
}
moveStack ( left , right , slotID ) ;
} ;
}
2021-02-13 22:30:50 +02:00
void CExchangeController : : moveStack (
const CGHeroInstance * source ,
const CGHeroInstance * target ,
SlotID sourceSlot )
{
auto creature = source - > getCreature ( sourceSlot ) ;
SlotID targetSlot = target - > getSlotFor ( creature ) ;
if ( targetSlot . validSlot ( ) )
{
if ( source - > stacksCount ( ) = = 1 & & source - > needsLastStack ( ) )
{
cb - > splitStack (
source ,
target ,
sourceSlot ,
targetSlot ,
target - > getStackCount ( targetSlot ) + source - > getStackCount ( sourceSlot ) - 1 ) ;
}
else
{
cb - > mergeOrSwapStacks ( source , target , sourceSlot , targetSlot ) ;
2021-02-11 21:06:47 +02:00
}
2021-02-13 22:30:50 +02:00
}
}
2021-02-11 21:06:47 +02:00
2021-02-13 22:30:50 +02:00
void CExchangeController : : moveArmy ( bool leftToRight )
{
const CGHeroInstance * source = leftToRight ? left : right ;
const CGHeroInstance * target = leftToRight ? right : left ;
2021-11-28 21:48:22 +02:00
const CGarrisonSlot * selection = this - > view - > getSelectedSlotID ( ) ;
SlotID slot ;
2021-02-13 22:30:50 +02:00
2021-11-28 21:48:22 +02:00
if ( source - > tempOwner ! = cb - > getMyColor ( ) )
2021-02-13 22:30:50 +02:00
{
2021-11-28 21:48:22 +02:00
return ;
}
2021-02-13 22:30:50 +02:00
2021-11-28 21:48:22 +02:00
if ( selection & & selection - > our ( ) & & selection - > getObj ( ) = = source )
{
slot = selection - > getSlot ( ) ;
}
else
{
auto weakestSlot = vstd : : minElementByFun (
source - > Slots ( ) ,
[ ] ( const std : : pair < SlotID , CStackInstance * > & s ) - > int
{
2023-04-05 02:26:29 +02:00
return s . second - > getCreatureID ( ) . toCreature ( ) - > getAIValue ( ) ;
2021-11-28 21:48:22 +02:00
} ) ;
2021-02-13 22:30:50 +02:00
2021-11-28 21:48:22 +02:00
slot = weakestSlot - > first ;
}
cb - > bulkMoveArmy ( source - > id , target - > id , slot ) ;
2021-02-13 22:30:50 +02:00
}
void CExchangeController : : moveArtifacts ( bool leftToRight )
{
const CGHeroInstance * source = leftToRight ? left : right ;
const CGHeroInstance * target = leftToRight ? right : left ;
2021-11-28 21:48:22 +02:00
if ( source - > tempOwner ! = cb - > getMyColor ( ) )
{
return ;
}
2021-02-14 17:11:46 +02:00
GsThread : : run ( [ = ]
2022-11-07 00:18:05 +02:00
{
2022-11-10 23:24:41 +02:00
cb - > bulkMoveArtifacts ( source - > id , target - > id , false ) ;
2021-02-11 21:06:47 +02:00
} ) ;
2020-03-31 22:50:32 +02:00
}
2021-02-13 22:30:50 +02:00
void CExchangeController : : moveArtifact (
const CGHeroInstance * source ,
const CGHeroInstance * target ,
ArtifactPosition srcPosition )
{
auto srcLocation = ArtifactLocation ( source , srcPosition ) ;
2022-11-06 23:41:29 +02:00
auto dstLocation = ArtifactLocation ( target ,
2023-03-21 12:13:53 +02:00
ArtifactUtils : : getArtAnyPosition ( target , source - > getArt ( srcPosition ) - > getTypeId ( ) ) ) ;
2021-02-13 22:30:50 +02:00
2022-11-06 23:41:29 +02:00
cb - > swapArtifacts ( srcLocation , dstLocation ) ;
2021-02-13 22:30:50 +02:00
}
2018-04-07 13:34:11 +02:00
CExchangeWindow : : CExchangeWindow ( ObjectInstanceID hero1 , ObjectInstanceID hero2 , QueryID queryID )
2021-11-28 21:48:22 +02:00
: CStatusbarWindow ( PLAYER_COLORED | BORDERED , isQuickExchangeLayoutAvailable ( ) ? QUICK_EXCHANGE_BG : " TRADE2 " ) ,
controller ( this , hero1 , hero2 ) ,
moveStackLeftButtons ( ) ,
moveStackRightButtons ( )
2009-06-19 15:10:36 +03:00
{
2021-11-28 21:48:22 +02:00
const bool qeLayout = isQuickExchangeLayoutAvailable ( ) ;
2020-03-31 22:50:32 +02:00
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2009-06-16 14:18:14 +03:00
2018-04-07 13:34:11 +02:00
heroInst [ 0 ] = LOCPLINT - > cb - > getHero ( hero1 ) ;
heroInst [ 1 ] = LOCPLINT - > cb - > getHero ( hero2 ) ;
auto genTitle = [ ] ( const CGHeroInstance * h )
2012-06-15 20:08:19 +03:00
{
2018-04-07 13:34:11 +02:00
boost : : format fmt ( CGI - > generaltexth - > allTexts [ 138 ] ) ;
2023-01-02 13:27:03 +02:00
fmt % h - > getNameTranslated ( ) % h - > level % h - > type - > heroClass - > getNameTranslated ( ) ;
2018-04-07 13:34:11 +02:00
return boost : : str ( fmt ) ;
2012-06-15 20:08:19 +03:00
} ;
2022-11-26 23:12:20 +02:00
titles [ 0 ] = std : : make_shared < CLabel > ( 147 , 25 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , genTitle ( heroInst [ 0 ] ) ) ;
titles [ 1 ] = std : : make_shared < CLabel > ( 653 , 25 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , genTitle ( heroInst [ 1 ] ) ) ;
2009-06-17 12:38:03 +03:00
2018-04-07 13:34:11 +02:00
auto PSKIL32 = std : : make_shared < CAnimation > ( " PSKIL32 " ) ;
PSKIL32 - > preload ( ) ;
2009-06-17 19:46:16 +03:00
2018-04-07 13:34:11 +02:00
auto SECSK32 = std : : make_shared < CAnimation > ( " SECSK32 " ) ;
2020-03-31 22:50:32 +02:00
for ( int g = 0 ; g < 4 ; + + g )
{
2021-11-28 21:48:22 +02:00
if ( qeLayout )
2020-03-31 22:50:32 +02:00
primSkillImages . push_back ( std : : make_shared < CAnimImage > ( PSKIL32 , g , Rect ( 389 , 12 + 26 * g , 22 , 22 ) ) ) ;
else
primSkillImages . push_back ( std : : make_shared < CAnimImage > ( PSKIL32 , g , 0 , 385 , 19 + 36 * g ) ) ;
}
2018-04-07 13:34:11 +02:00
for ( int leftRight : { 0 , 1 } )
2009-06-17 19:46:16 +03:00
{
2018-04-07 13:34:11 +02:00
const CGHeroInstance * hero = heroInst . at ( leftRight ) ;
2009-06-17 19:46:16 +03:00
2018-04-07 13:34:11 +02:00
for ( int m = 0 ; m < GameConstants : : PRIMARY_SKILLS ; + + m )
2022-11-26 23:12:20 +02:00
primSkillValues [ leftRight ] . push_back ( std : : make_shared < CLabel > ( 352 + ( qeLayout ? 96 : 93 ) * leftRight , ( qeLayout ? 22 : 35 ) + ( qeLayout ? 26 : 36 ) * m , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ) ;
2009-06-28 16:49:39 +03:00
2018-04-07 13:34:11 +02:00
for ( int m = 0 ; m < hero - > secSkills . size ( ) ; + + m )
2021-11-28 21:48:22 +02:00
secSkillIcons [ leftRight ] . push_back ( std : : make_shared < CAnimImage > ( SECSK32 , 0 , 0 , 32 + 36 * m + 454 * leftRight , qeLayout ? 83 : 88 ) ) ;
2009-06-28 16:49:39 +03:00
2021-11-28 21:48:22 +02:00
specImages [ leftRight ] = std : : make_shared < CAnimImage > ( " UN32 " , hero - > type - > imageIndex , 0 , 67 + 490 * leftRight , qeLayout ? 41 : 45 ) ;
2009-06-28 16:49:39 +03:00
2021-11-28 21:48:22 +02:00
expImages [ leftRight ] = std : : make_shared < CAnimImage > ( PSKIL32 , 4 , 0 , 103 + 490 * leftRight , qeLayout ? 41 : 45 ) ;
2022-11-26 23:12:20 +02:00
expValues [ leftRight ] = std : : make_shared < CLabel > ( 119 + 490 * leftRight , qeLayout ? 66 : 71 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2018-04-07 13:34:11 +02:00
2021-11-28 21:48:22 +02:00
manaImages [ leftRight ] = std : : make_shared < CAnimImage > ( PSKIL32 , 5 , 0 , 139 + 490 * leftRight , qeLayout ? 41 : 45 ) ;
2022-11-26 23:12:20 +02:00
manaValues [ leftRight ] = std : : make_shared < CLabel > ( 155 + 490 * leftRight , qeLayout ? 66 : 71 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2018-04-07 13:34:11 +02:00
}
2009-06-28 16:49:39 +03:00
2018-04-07 13:34:11 +02:00
portraits [ 0 ] = std : : make_shared < CAnimImage > ( " PortraitsLarge " , heroInst [ 0 ] - > portrait , 0 , 257 , 13 ) ;
portraits [ 1 ] = std : : make_shared < CAnimImage > ( " PortraitsLarge " , heroInst [ 1 ] - > portrait , 0 , 485 , 13 ) ;
2009-07-27 20:55:56 +03:00
2023-04-23 13:33:47 +02:00
artifs [ 0 ] = std : : make_shared < CArtifactsOfHeroMain > ( Point ( - 334 , 150 ) ) ;
2009-11-28 21:55:40 +02:00
artifs [ 0 ] - > setHero ( heroInst [ 0 ] ) ;
2023-04-23 13:33:47 +02:00
artifs [ 1 ] = std : : make_shared < CArtifactsOfHeroMain > ( Point ( 98 , 150 ) ) ;
2009-06-28 16:49:39 +03:00
artifs [ 1 ] - > setHero ( heroInst [ 1 ] ) ;
2018-04-07 13:34:11 +02:00
addSet ( artifs [ 0 ] ) ;
addSet ( artifs [ 1 ] ) ;
2009-06-28 16:49:39 +03:00
for ( int g = 0 ; g < 4 ; + + g )
{
2018-04-07 13:34:11 +02:00
primSkillAreas . push_back ( std : : make_shared < LRClickableAreaWTextComp > ( ) ) ;
2021-11-28 21:48:22 +02:00
if ( qeLayout )
2023-03-15 12:17:08 +02:00
primSkillAreas [ g ] - > pos = Rect ( Point ( pos . x + 324 , pos . y + 12 + 26 * g ) , Point ( 152 , 22 ) ) ;
2020-03-31 22:50:32 +02:00
else
2023-03-15 12:17:08 +02:00
primSkillAreas [ g ] - > pos = Rect ( Point ( pos . x + 329 , pos . y + 19 + 36 * g ) , Point ( 140 , 32 ) ) ;
2009-06-28 16:49:39 +03:00
primSkillAreas [ g ] - > text = CGI - > generaltexth - > arraytxt [ 2 + g ] ;
primSkillAreas [ g ] - > type = g ;
2023-03-15 12:17:08 +02:00
primSkillAreas [ g ] - > bonusValue = 0 ;
2010-02-01 01:30:47 +02:00
primSkillAreas [ g ] - > baseType = 0 ;
2014-02-26 20:32:42 +03:00
primSkillAreas [ g ] - > hoverText = CGI - > generaltexth - > heroscrn [ 1 ] ;
boost : : replace_first ( primSkillAreas [ g ] - > hoverText , " %s " , CGI - > generaltexth - > primarySkillNames [ g ] ) ;
2009-06-28 16:49:39 +03:00
}
//heroes related thing
2018-04-07 13:34:11 +02:00
for ( int b = 0 ; b < heroInst . size ( ) ; b + + )
2009-06-28 16:49:39 +03:00
{
2018-04-07 13:34:11 +02:00
const CGHeroInstance * hero = heroInst . at ( b ) ;
2009-06-19 15:10:36 +03:00
//secondary skill's clickable areas
2018-04-07 13:34:11 +02:00
for ( int g = 0 ; g < hero - > secSkills . size ( ) ; + + g )
2009-06-19 15:10:36 +03:00
{
2018-04-07 13:34:11 +02:00
int skill = hero - > secSkills [ g ] . first ,
level = hero - > secSkills [ g ] . second ; // <1, 3>
secSkillAreas [ b ] . push_back ( std : : make_shared < LRClickableAreaWTextComp > ( ) ) ;
2023-02-08 13:56:09 +02:00
secSkillAreas [ b ] [ g ] - > pos = Rect ( Point ( pos . x + 32 + g * 36 + b * 454 , pos . y + ( qeLayout ? 83 : 88 ) ) , Point ( 32 , 32 ) ) ;
2009-06-19 15:10:36 +03:00
secSkillAreas [ b ] [ g ] - > baseType = 1 ;
2009-11-13 18:02:25 +02:00
secSkillAreas [ b ] [ g ] - > type = skill ;
2010-07-13 08:25:40 +03:00
secSkillAreas [ b ] [ g ] - > bonusValue = level ;
2023-01-01 22:20:41 +02:00
secSkillAreas [ b ] [ g ] - > text = CGI - > skillh - > getByIndex ( skill ) - > getDescriptionTranslated ( level ) ;
2009-06-19 15:10:36 +03:00
2014-02-26 20:32:42 +03:00
secSkillAreas [ b ] [ g ] - > hoverText = CGI - > generaltexth - > heroscrn [ 21 ] ;
boost : : algorithm : : replace_first ( secSkillAreas [ b ] [ g ] - > hoverText , " %s " , CGI - > generaltexth - > levels [ level - 1 ] ) ;
2023-01-01 22:20:41 +02:00
boost : : algorithm : : replace_first ( secSkillAreas [ b ] [ g ] - > hoverText , " %s " , CGI - > skillh - > getByIndex ( skill ) - > getNameTranslated ( ) ) ;
2009-06-19 15:10:36 +03:00
}
2010-02-01 01:30:47 +02:00
2018-04-07 13:34:11 +02:00
heroAreas [ b ] = std : : make_shared < CHeroArea > ( 257 + 228 * b , 13 , hero ) ;
specialtyAreas [ b ] = std : : make_shared < LRClickableAreaWText > ( ) ;
2023-02-08 13:56:09 +02:00
specialtyAreas [ b ] - > pos = Rect ( Point ( pos . x + 69 + 490 * b , pos . y + ( qeLayout ? 41 : 45 ) ) , Point ( 32 , 32 ) ) ;
2018-04-07 13:34:11 +02:00
specialtyAreas [ b ] - > hoverText = CGI - > generaltexth - > heroscrn [ 27 ] ;
2023-01-02 13:27:03 +02:00
specialtyAreas [ b ] - > text = hero - > type - > getSpecialtyDescriptionTranslated ( ) ;
2018-04-07 13:34:11 +02:00
experienceAreas [ b ] = std : : make_shared < LRClickableAreaWText > ( ) ;
2023-02-08 13:56:09 +02:00
experienceAreas [ b ] - > pos = Rect ( Point ( pos . x + 105 + 490 * b , pos . y + ( qeLayout ? 41 : 45 ) ) , Point ( 32 , 32 ) ) ;
2018-04-07 13:34:11 +02:00
experienceAreas [ b ] - > hoverText = CGI - > generaltexth - > heroscrn [ 9 ] ;
experienceAreas [ b ] - > text = CGI - > generaltexth - > allTexts [ 2 ] ;
2023-03-09 15:36:46 +02:00
boost : : algorithm : : replace_first ( experienceAreas [ b ] - > text , " %d " , std : : to_string ( hero - > level ) ) ;
boost : : algorithm : : replace_first ( experienceAreas [ b ] - > text , " %d " , std : : to_string ( CGI - > heroh - > reqExp ( hero - > level + 1 ) ) ) ;
boost : : algorithm : : replace_first ( experienceAreas [ b ] - > text , " %d " , std : : to_string ( hero - > exp ) ) ;
2018-04-07 13:34:11 +02:00
spellPointsAreas [ b ] = std : : make_shared < LRClickableAreaWText > ( ) ;
2023-02-08 13:56:09 +02:00
spellPointsAreas [ b ] - > pos = Rect ( Point ( pos . x + 141 + 490 * b , pos . y + ( qeLayout ? 41 : 45 ) ) , Point ( 32 , 32 ) ) ;
2018-04-07 13:34:11 +02:00
spellPointsAreas [ b ] - > hoverText = CGI - > generaltexth - > heroscrn [ 22 ] ;
spellPointsAreas [ b ] - > text = CGI - > generaltexth - > allTexts [ 205 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( spellPointsAreas [ b ] - > text , " %s " , hero - > getNameTranslated ( ) ) ;
2023-03-09 15:36:46 +02:00
boost : : algorithm : : replace_first ( spellPointsAreas [ b ] - > text , " %d " , std : : to_string ( hero - > mana ) ) ;
boost : : algorithm : : replace_first ( spellPointsAreas [ b ] - > text , " %d " , std : : to_string ( hero - > manaLimit ( ) ) ) ;
2018-04-07 13:34:11 +02:00
2023-02-03 19:17:59 +02:00
morale [ b ] = std : : make_shared < MoraleLuckBox > ( true , Rect ( Point ( 176 + 490 * b , 39 ) , Point ( 32 , 32 ) ) , true ) ;
luck [ b ] = std : : make_shared < MoraleLuckBox > ( false , Rect ( Point ( 212 + 490 * b , 39 ) , Point ( 32 , 32 ) ) , true ) ;
2009-06-17 19:46:16 +03:00
}
2009-06-17 12:38:03 +03:00
2023-04-28 13:22:03 +02:00
quit = std : : make_shared < CButton > ( Point ( 732 , 567 ) , " IOKAY.DEF " , CGI - > generaltexth - > zelp [ 600 ] , std : : bind ( & CExchangeWindow : : close , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2013-05-27 13:53:28 +03:00
if ( queryID . getNum ( ) > 0 )
2017-07-19 01:06:05 +02:00
quit - > addCallback ( [ = ] ( ) { LOCPLINT - > cb - > selectionMade ( 0 , queryID ) ; } ) ;
2013-05-27 13:53:28 +03:00
2021-11-28 21:48:22 +02:00
questlogButton [ 0 ] = std : : make_shared < CButton > ( Point ( 10 , qeLayout ? 39 : 44 ) , " hsbtns4.def " , CButton : : tooltip ( CGI - > generaltexth - > heroscrn [ 0 ] ) , std : : bind ( & CExchangeWindow : : questlog , this , 0 ) ) ;
questlogButton [ 1 ] = std : : make_shared < CButton > ( Point ( 740 , qeLayout ? 39 : 44 ) , " hsbtns4.def " , CButton : : tooltip ( CGI - > generaltexth - > heroscrn [ 0 ] ) , std : : bind ( & CExchangeWindow : : questlog , this , 1 ) ) ;
2009-06-19 15:10:36 +03:00
2012-02-21 17:08:42 +03:00
Rect barRect ( 5 , 578 , 725 , 18 ) ;
2023-01-30 13:58:13 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , barRect , 5 , 578 ) ) ;
2009-06-19 15:10:36 +03:00
2009-06-28 11:21:50 +03:00
//garrison interface
2018-11-14 19:58:37 +02:00
2021-11-28 21:48:22 +02:00
garr = std : : make_shared < CGarrisonInt > ( 69 , qeLayout ? 122 : 131 , 4 , Point ( 418 , 0 ) , heroInst [ 0 ] , heroInst [ 1 ] , true , true ) ;
2018-11-14 19:58:37 +02:00
auto splitButtonCallback = [ & ] ( ) { garr - > splitClick ( ) ; } ;
2021-11-28 21:48:22 +02:00
garr - > addSplitBtn ( std : : make_shared < CButton > ( Point ( 10 , qeLayout ? 122 : 132 ) , " TSBTNS.DEF " , CButton : : tooltip ( CGI - > generaltexth - > tcommands [ 3 ] ) , splitButtonCallback ) ) ;
garr - > addSplitBtn ( std : : make_shared < CButton > ( Point ( 744 , qeLayout ? 122 : 132 ) , " TSBTNS.DEF " , CButton : : tooltip ( CGI - > generaltexth - > tcommands [ 3 ] ) , splitButtonCallback ) ) ;
2018-04-07 13:34:11 +02:00
2023-01-01 22:50:38 +02:00
if ( qeLayout )
2020-04-01 00:01:57 +02:00
{
2021-11-28 21:48:22 +02:00
moveAllGarrButtonLeft = std : : make_shared < CButton > ( Point ( 325 , 118 ) , QUICK_EXCHANGE_MOD_PREFIX + " /armRight.DEF " , CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 1 ] ) , controller . onMoveArmyToRight ( ) ) ;
echangeGarrButton = std : : make_shared < CButton > ( Point ( 377 , 118 ) , QUICK_EXCHANGE_MOD_PREFIX + " /swapAll.DEF " , CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 2 ] ) , controller . onSwapArmy ( ) ) ;
moveAllGarrButtonRight = std : : make_shared < CButton > ( Point ( 425 , 118 ) , QUICK_EXCHANGE_MOD_PREFIX + " /armLeft.DEF " , CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 1 ] ) , controller . onMoveArmyToLeft ( ) ) ;
moveArtifactsButtonLeft = std : : make_shared < CButton > ( Point ( 325 , 154 ) , QUICK_EXCHANGE_MOD_PREFIX + " /artRight.DEF " , CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 3 ] ) , controller . onMoveArtifactsToRight ( ) ) ;
echangeArtifactsButton = std : : make_shared < CButton > ( Point ( 377 , 154 ) , QUICK_EXCHANGE_MOD_PREFIX + " /swapAll.DEF " , CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 4 ] ) , controller . onSwapArtifacts ( ) ) ;
moveArtifactsButtonRight = std : : make_shared < CButton > ( Point ( 425 , 154 ) , QUICK_EXCHANGE_MOD_PREFIX + " /artLeft.DEF " , CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 3 ] ) , controller . onMoveArtifactsToLeft ( ) ) ;
for ( int i = 0 ; i < GameConstants : : ARMY_SIZE ; i + + )
{
moveStackLeftButtons . push_back (
std : : make_shared < CButton > (
Point ( 484 + 35 * i , 154 ) ,
QUICK_EXCHANGE_MOD_PREFIX + " /unitLeft.DEF " ,
CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 1 ] ) ,
controller . onMoveStackToLeft ( SlotID ( i ) ) ) ) ;
moveStackRightButtons . push_back (
std : : make_shared < CButton > (
Point ( 66 + 35 * i , 154 ) ,
QUICK_EXCHANGE_MOD_PREFIX + " /unitRight.DEF " ,
CButton : : tooltip ( CGI - > generaltexth - > qeModCommands [ 1 ] ) ,
controller . onMoveStackToRight ( SlotID ( i ) ) ) ) ;
}
2020-04-01 00:01:57 +02:00
}
2018-04-07 13:34:11 +02:00
updateWidgets ( ) ;
2009-06-16 14:18:14 +03:00
}
2021-11-28 21:48:22 +02:00
const CGarrisonSlot * CExchangeWindow : : getSelectedSlotID ( ) const
{
return garr - > getSelection ( ) ;
}
2018-04-07 13:34:11 +02:00
void CExchangeWindow : : updateGarrisons ( )
{
garr - > recreateSlots ( ) ;
updateWidgets ( ) ;
}
void CExchangeWindow : : questlog ( int whichHero )
{
CCS - > curh - > dragAndDropCursor ( nullptr ) ;
LOCPLINT - > showQuestLog ( ) ;
}
void CExchangeWindow : : updateWidgets ( )
{
for ( size_t leftRight : { 0 , 1 } )
{
const CGHeroInstance * hero = heroInst . at ( leftRight ) ;
for ( int m = 0 ; m < GameConstants : : PRIMARY_SKILLS ; + + m )
{
2023-07-17 21:24:43 +02:00
auto value = heroInst [ leftRight ] - > getPrimSkillLevel ( static_cast < PrimarySkill : : PrimarySkill > ( m ) ) ;
2023-03-09 15:36:46 +02:00
primSkillValues [ leftRight ] [ m ] - > setText ( std : : to_string ( value ) ) ;
2018-04-07 13:34:11 +02:00
}
for ( int m = 0 ; m < hero - > secSkills . size ( ) ; + + m )
{
int id = hero - > secSkills [ m ] . first ;
int level = hero - > secSkills [ m ] . second ;
secSkillIcons [ leftRight ] [ m ] - > setFrame ( 2 + id * 3 + level ) ;
}
2023-02-12 23:52:35 +02:00
expValues [ leftRight ] - > setText ( TextOperations : : formatMetric ( hero - > exp , 3 ) ) ;
manaValues [ leftRight ] - > setText ( TextOperations : : formatMetric ( hero - > mana , 3 ) ) ;
2018-04-07 13:34:11 +02:00
morale [ leftRight ] - > set ( hero ) ;
luck [ leftRight ] - > set ( hero ) ;
}
}
2023-04-20 19:20:51 +02:00
CShipyardWindow : : CShipyardWindow ( const TResources & cost , int state , BoatId boatType , const std : : function < void ( ) > & onBuy )
2018-10-29 15:12:07 +02:00
: CStatusbarWindow ( PLAYER_COLORED , " TPSHIP " )
2009-07-26 06:33:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2009-07-26 06:33:13 +03:00
2018-04-07 13:34:11 +02:00
bgWater = std : : make_shared < CPicture > ( " TPSHIPBK " , 100 , 69 ) ;
2009-07-26 06:33:13 +03:00
2023-06-07 18:51:44 +02:00
auto handler = CGI - > objtypeh - > getHandlerFor ( Obj : : BOAT , boatType ) ;
2009-07-26 06:33:13 +03:00
2023-06-07 18:51:44 +02:00
auto boatConstructor = std : : dynamic_pointer_cast < const BoatInstanceConstructor > ( handler ) ;
assert ( boatConstructor ) ;
if ( boatConstructor )
{
std : : string boatFilename = boatConstructor - > getBoatAnimationName ( ) ;
Point waterCenter = Point ( bgWater - > pos . x + bgWater - > pos . w / 2 , bgWater - > pos . y + bgWater - > pos . h / 2 ) ;
bgShip = std : : make_shared < CAnimImage > ( boatFilename , 0 , 7 , 120 , 96 , 0 ) ;
bgShip - > center ( waterCenter ) ;
}
2009-06-18 18:05:00 +03:00
2011-09-23 18:58:18 +03:00
// Create resource icons and costs.
2023-04-05 02:26:29 +02:00
std : : string goldValue = std : : to_string ( cost [ EGameResID : : GOLD ] ) ;
std : : string woodValue = std : : to_string ( cost [ EGameResID : : WOOD ] ) ;
2009-07-26 06:33:13 +03:00
2022-11-26 23:12:20 +02:00
goldCost = std : : make_shared < CLabel > ( 118 , 294 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , goldValue ) ;
woodCost = std : : make_shared < CLabel > ( 212 , 294 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , woodValue ) ;
2011-09-23 18:58:18 +03:00
2023-04-05 02:26:29 +02:00
goldPic = std : : make_shared < CAnimImage > ( " RESOURCE " , GameResID ( EGameResID : : GOLD ) , 0 , 100 , 244 ) ;
woodPic = std : : make_shared < CAnimImage > ( " RESOURCE " , GameResID ( EGameResID : : WOOD ) , 0 , 196 , 244 ) ;
2009-07-26 06:33:13 +03:00
2023-04-27 19:21:06 +02:00
quit = std : : make_shared < CButton > ( Point ( 224 , 312 ) , " ICANCEL " , CButton : : tooltip ( CGI - > generaltexth - > allTexts [ 599 ] ) , std : : bind ( & CShipyardWindow : : close , this ) , EShortcut : : GLOBAL_CANCEL ) ;
2023-04-28 13:22:03 +02:00
build = std : : make_shared < CButton > ( Point ( 42 , 312 ) , " IBUY30 " , CButton : : tooltip ( CGI - > generaltexth - > allTexts [ 598 ] ) , std : : bind ( & CShipyardWindow : : close , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2014-08-03 14:16:19 +03:00
build - > addCallback ( onBuy ) ;
2009-08-17 20:19:09 +03:00
2023-04-27 23:29:16 +02:00
for ( GameResID i = EGameResID : : WOOD ; i < = EGameResID : : GOLD ; + + i )
2009-07-26 06:33:13 +03:00
{
if ( cost [ i ] > LOCPLINT - > cb - > getResourceAmount ( i ) )
{
2011-09-23 18:58:18 +03:00
build - > block ( true ) ;
2009-07-26 06:33:13 +03:00
break ;
}
}
2022-11-29 17:07:21 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2009-07-26 06:33:13 +03:00
2022-11-26 23:12:20 +02:00
title = std : : make_shared < CLabel > ( 164 , 27 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > jktexts [ 13 ] ) ;
costLabel = std : : make_shared < CLabel > ( 164 , 220 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > jktexts [ 14 ] ) ;
2009-07-26 06:33:13 +03:00
}
2009-08-31 18:57:15 +03:00
2010-07-03 15:00:53 +03:00
void CTransformerWindow : : CItem : : move ( )
{
2018-04-07 13:34:11 +02:00
if ( left )
2012-05-13 18:04:21 +03:00
moveBy ( Point ( 289 , 0 ) ) ;
2010-07-03 15:00:53 +03:00
else
2012-05-13 18:04:21 +03:00
moveBy ( Point ( - 289 , 0 ) ) ;
2010-07-03 15:00:53 +03:00
left = ! left ;
}
2023-07-09 16:48:25 +02:00
void CTransformerWindow : : CItem : : clickPressed ( const Point & cursorPosition )
2010-07-03 15:00:53 +03:00
{
2023-07-08 13:33:04 +02:00
move ( ) ;
parent - > redraw ( ) ;
2010-07-03 15:00:53 +03:00
}
2012-06-17 01:40:28 +03:00
void CTransformerWindow : : CItem : : update ( )
{
2023-04-05 02:26:29 +02:00
icon - > setFrame ( parent - > army - > getCreature ( SlotID ( id ) ) - > getId ( ) + 2 ) ;
2012-06-17 01:40:28 +03:00
}
2018-04-07 13:34:11 +02:00
CTransformerWindow : : CItem : : CItem ( CTransformerWindow * parent_ , int size_ , int id_ )
: CIntObject ( LCLICK ) ,
id ( id_ ) ,
size ( size_ ) ,
parent ( parent_ )
2010-07-03 15:00:53 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2010-07-20 09:05:45 +03:00
left = true ;
2010-07-03 15:00:53 +03:00
pos . w = 58 ;
pos . h = 64 ;
2012-01-12 18:23:00 +03:00
2010-07-03 15:00:53 +03:00
pos . x + = 45 + ( id % 3 ) * 83 + id / 6 * 83 ;
pos . y + = 109 + ( id / 3 ) * 98 ;
2023-04-05 02:26:29 +02:00
icon = std : : make_shared < CAnimImage > ( " TWCRPORT " , parent - > army - > getCreature ( SlotID ( id ) ) - > getId ( ) + 2 ) ;
2023-03-09 15:36:46 +02:00
count = std : : make_shared < CLabel > ( 28 , 76 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , std : : to_string ( size ) ) ;
2010-07-03 15:00:53 +03:00
}
void CTransformerWindow : : makeDeal ( )
{
2018-04-07 13:34:11 +02:00
for ( auto & elem : items )
{
if ( ! elem - > left )
2023-04-28 03:16:37 +02:00
LOCPLINT - > cb - > trade ( market , EMarketMode : : CREATURE_UNDEAD , elem - > id , 0 , 0 , hero ) ;
2018-04-07 13:34:11 +02:00
}
2010-07-03 15:00:53 +03:00
}
void CTransformerWindow : : addAll ( )
{
2018-04-07 13:34:11 +02:00
for ( auto & elem : items )
{
if ( elem - > left )
2013-06-29 16:05:48 +03:00
elem - > move ( ) ;
2018-04-07 13:34:11 +02:00
}
2018-07-25 00:36:48 +02:00
redraw ( ) ;
2010-07-03 15:00:53 +03:00
}
2012-06-17 01:40:28 +03:00
void CTransformerWindow : : updateGarrisons ( )
{
2013-06-29 16:05:48 +03:00
for ( auto & item : items )
2012-06-17 01:40:28 +03:00
item - > update ( ) ;
}
2023-04-28 03:16:37 +02:00
CTransformerWindow : : CTransformerWindow ( const IMarket * _market , const CGHeroInstance * _hero )
2018-10-29 15:12:07 +02:00
: CStatusbarWindow ( PLAYER_COLORED , " SKTRNBK " ) ,
2015-01-18 19:23:23 +02:00
hero ( _hero ) ,
2023-04-28 03:16:37 +02:00
market ( _market )
2010-07-03 15:00:53 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
if ( hero )
2010-07-03 15:00:53 +03:00
army = hero ;
else
2023-04-28 03:16:37 +02:00
army = dynamic_cast < const CArmedInstance * > ( market ) ; //for town only
if ( army )
2018-04-07 13:34:11 +02:00
{
2023-04-28 03:16:37 +02:00
for ( int i = 0 ; i < GameConstants : : ARMY_SIZE ; i + + )
{
if ( army - > getCreature ( SlotID ( i ) ) )
items . push_back ( std : : make_shared < CItem > ( this , army - > getStackCount ( SlotID ( i ) ) , i ) ) ;
}
2018-04-07 13:34:11 +02:00
}
2012-01-12 18:23:00 +03:00
2023-04-27 19:21:06 +02:00
all = std : : make_shared < CButton > ( Point ( 146 , 416 ) , " ALTARMY.DEF " , CGI - > generaltexth - > zelp [ 590 ] , [ & ] ( ) { addAll ( ) ; } , EShortcut : : RECRUITMENT_UPGRADE_ALL ) ;
2023-04-28 13:22:03 +02:00
convert = std : : make_shared < CButton > ( Point ( 269 , 416 ) , " ALTSACR.DEF " , CGI - > generaltexth - > zelp [ 591 ] , [ & ] ( ) { makeDeal ( ) ; } , EShortcut : : GLOBAL_ACCEPT ) ;
2023-04-27 19:21:06 +02:00
cancel = std : : make_shared < CButton > ( Point ( 392 , 416 ) , " ICANCEL.DEF " , CGI - > generaltexth - > zelp [ 592 ] , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_CANCEL ) ;
2022-11-29 17:07:21 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2012-06-17 01:40:28 +03:00
2022-11-26 23:12:20 +02:00
titleLeft = std : : make_shared < CLabel > ( 153 , 29 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 485 ] ) ; //holding area
titleRight = std : : make_shared < CLabel > ( 153 + 295 , 29 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 486 ] ) ; //transformer
helpLeft = std : : make_shared < CTextBox > ( CGI - > generaltexth - > allTexts [ 487 ] , Rect ( 26 , 56 , 255 , 40 ) , 0 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW ) ; //move creatures to create skeletons
helpRight = std : : make_shared < CTextBox > ( CGI - > generaltexth - > allTexts [ 488 ] , Rect ( 320 , 56 , 255 , 40 ) , 0 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW ) ; //creatures here will become skeletons
2018-04-07 13:34:11 +02:00
}
2012-06-17 01:40:28 +03:00
2018-04-07 13:34:11 +02:00
CUniversityWindow : : CItem : : CItem ( CUniversityWindow * _parent , int _ID , int X , int Y )
2023-06-13 18:33:35 +02:00
: CIntObject ( LCLICK | SHOW_POPUP | HOVER ) ,
2018-04-07 13:34:11 +02:00
ID ( _ID ) ,
parent ( _parent )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
pos . x + = X ;
pos . y + = Y ;
topBar = std : : make_shared < CAnimImage > ( parent - > bars , 0 , 0 , - 28 , - 22 ) ;
bottomBar = std : : make_shared < CAnimImage > ( parent - > bars , 0 , 0 , - 28 , 48 ) ;
icon = std : : make_shared < CAnimImage > ( " SECSKILL " , _ID * 3 + 3 , 0 ) ;
2023-01-01 22:20:41 +02:00
name = std : : make_shared < CLabel > ( 22 , - 13 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > skillh - > getByIndex ( ID ) - > getNameTranslated ( ) ) ;
2022-11-26 23:12:20 +02:00
level = std : : make_shared < CLabel > ( 22 , 57 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > levels [ 0 ] ) ;
2018-04-07 13:34:11 +02:00
pos . h = icon - > pos . h ;
pos . w = icon - > pos . w ;
2010-07-03 15:00:53 +03:00
}
2023-07-09 16:48:25 +02:00
void CUniversityWindow : : CItem : : clickPressed ( const Point & cursorPosition )
2010-07-20 17:08:13 +03:00
{
2023-07-08 13:33:04 +02:00
if ( state ( ) = = 2 )
GH . windows ( ) . createAndPushWindow < CUnivConfirmWindow > ( parent , ID , LOCPLINT - > cb - > getResourceAmount ( EGameResID : : GOLD ) > = 2000 ) ;
2010-07-20 17:08:13 +03:00
}
2023-07-08 13:33:04 +02:00
void CUniversityWindow : : CItem : : showPopupWindow ( const Point & cursorPosition )
2010-07-20 17:08:13 +03:00
{
2023-06-11 17:20:10 +02:00
CRClickPopup : : createAndPush ( CGI - > skillh - > getByIndex ( ID ) - > getDescriptionTranslated ( 1 ) , std : : make_shared < CComponent > ( CComponent : : secskill , ID , 1 ) ) ;
2010-07-20 17:08:13 +03:00
}
void CUniversityWindow : : CItem : : 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 - > skillh - > getByIndex ( ID ) - > getNameTranslated ( ) ) ;
2010-07-20 17:08:13 +03:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2010-07-20 17:08:13 +03:00
}
int CUniversityWindow : : CItem : : state ( )
{
2018-04-07 13:34:11 +02:00
if ( parent - > hero - > getSecSkillLevel ( SecondarySkill ( ID ) ) ) //hero know this skill
2010-07-20 17:08:13 +03:00
return 1 ;
2022-11-14 19:08:49 +02:00
if ( ! parent - > hero - > canLearnSkill ( SecondarySkill ( ID ) ) ) //can't learn more skills
2010-07-22 03:32:45 +03:00
return 0 ;
2010-07-20 17:08:13 +03:00
return 2 ;
}
2023-06-02 15:42:18 +02:00
void CUniversityWindow : : CItem : : showAll ( Canvas & to )
2010-07-20 17:08:13 +03:00
{
2018-04-07 13:34:11 +02:00
//TODO: update when state actually changes
auto stateIndex = state ( ) ;
topBar - > setFrame ( stateIndex ) ;
bottomBar - > setFrame ( stateIndex ) ;
2010-07-20 17:08:13 +03:00
2018-04-07 13:34:11 +02:00
CIntObject : : showAll ( to ) ;
2010-07-20 17:08:13 +03:00
}
2018-04-07 13:34:11 +02:00
CUniversityWindow : : CUniversityWindow ( const CGHeroInstance * _hero , const IMarket * _market )
2018-10-29 15:12:07 +02:00
: CStatusbarWindow ( PLAYER_COLORED , " UNIVERS1 " ) ,
2015-01-18 19:23:23 +02:00
hero ( _hero ) ,
market ( _market )
2010-07-20 17:08:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2010-08-06 16:14:10 +03:00
2018-04-07 13:34:11 +02:00
bars = std : : make_shared < CAnimation > ( ) ;
bars - > setCustom ( " UNIVRED " , 0 , 0 ) ;
bars - > setCustom ( " UNIVGOLD " , 1 , 0 ) ;
bars - > setCustom ( " UNIVGREN " , 2 , 0 ) ;
bars - > preload ( ) ;
2023-04-28 03:16:37 +02:00
std : : string titleStr = CGI - > generaltexth - > allTexts [ 602 ] ;
std : : string speechStr = CGI - > generaltexth - > allTexts [ 603 ] ;
2010-07-20 17:08:13 +03:00
2023-04-26 22:18:43 +02:00
if ( auto town = dynamic_cast < const CGTownInstance * > ( _market ) )
2020-10-25 00:04:34 +02:00
{
2023-04-26 22:18:43 +02:00
auto faction = town - > town - > faction - > getId ( ) ;
auto bid = town - > town - > getSpecialBuilding ( BuildingSubID : : MAGIC_UNIVERSITY ) - > bid ;
titlePic = std : : make_shared < CAnimImage > ( ( * CGI - > townh ) [ faction ] - > town - > clientInfo . buildingsIcons , bid ) ;
2020-10-25 00:04:34 +02:00
}
2023-04-28 03:16:37 +02:00
else if ( auto uni = dynamic_cast < const CGUniversity * > ( _market ) ; uni - > appearance )
{
titlePic = std : : make_shared < CAnimImage > ( uni - > appearance - > animationFile , 0 ) ;
titleStr = uni - > title ;
speechStr = uni - > speech ;
}
2010-07-20 17:08:13 +03:00
else
2023-04-28 03:16:37 +02:00
{
2018-04-07 13:34:11 +02:00
titlePic = std : : make_shared < CPicture > ( " UNIVBLDG " ) ;
2023-04-28 03:16:37 +02:00
}
2010-07-20 17:08:13 +03:00
2012-12-13 16:07:56 +03:00
titlePic - > center ( Point ( 232 + pos . x , 76 + pos . y ) ) ;
2012-06-15 20:08:19 +03:00
2023-04-28 03:16:37 +02:00
clerkSpeech = std : : make_shared < CTextBox > ( speechStr , Rect ( 24 , 129 , 413 , 70 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
title = std : : make_shared < CLabel > ( 231 , 26 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW , titleStr ) ;
2012-06-15 20:08:19 +03:00
2018-04-07 13:34:11 +02:00
std : : vector < int > goods = market - > availableItemsIds ( EMarketMode : : RESOURCE_SKILL ) ;
2012-06-15 20:08:19 +03:00
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < goods . size ( ) ; i + + ) //prepare clickable items
items . push_back ( std : : make_shared < CItem > ( this , goods [ i ] , 54 + i * 104 , 234 ) ) ;
2012-01-12 18:23:00 +03:00
2023-04-28 13:22:03 +02:00
cancel = std : : make_shared < CButton > ( Point ( 200 , 313 ) , " IOKAY.DEF " , CGI - > generaltexth - > zelp [ 632 ] , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_ACCEPT ) ;
2022-11-29 17:07:21 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2018-04-07 13:34:11 +02:00
}
2012-01-12 18:23:00 +03:00
2018-04-07 13:34:11 +02:00
void CUniversityWindow : : makeDeal ( int skill )
{
2023-04-28 03:16:37 +02:00
LOCPLINT - > cb - > trade ( market , EMarketMode : : RESOURCE_SKILL , 6 , skill , 1 , hero ) ;
2010-07-20 17:08:13 +03:00
}
2018-04-07 13:34:11 +02:00
CUnivConfirmWindow : : CUnivConfirmWindow ( CUniversityWindow * owner_ , int SKILL , bool available )
2018-10-29 15:12:07 +02:00
: CStatusbarWindow ( PLAYER_COLORED , " UNIVERS2.PCX " ) ,
2018-04-07 13:34:11 +02:00
owner ( owner_ )
2010-07-20 17:08:13 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2010-07-20 17:08:13 +03:00
std : : string text = CGI - > generaltexth - > allTexts [ 608 ] ;
boost : : replace_first ( text , " %s " , CGI - > generaltexth - > levels [ 0 ] ) ;
2023-01-01 22:20:41 +02:00
boost : : replace_first ( text , " %s " , CGI - > skillh - > getByIndex ( SKILL ) - > getNameTranslated ( ) ) ;
2010-07-20 17:08:13 +03:00
boost : : replace_first ( text , " %d " , " 2000 " ) ;
2022-11-26 23:12:20 +02:00
clerkSpeech = std : : make_shared < CTextBox > ( text , Rect ( 24 , 129 , 413 , 70 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2012-06-15 20:08:19 +03:00
2023-01-01 22:20:41 +02:00
name = std : : make_shared < CLabel > ( 230 , 37 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > skillh - > getByIndex ( SKILL ) - > getNameTranslated ( ) ) ;
2018-04-07 13:34:11 +02:00
icon = std : : make_shared < CAnimImage > ( " SECSKILL " , SKILL * 3 + 3 , 0 , 211 , 51 ) ;
2022-11-26 23:12:20 +02:00
level = std : : make_shared < CLabel > ( 230 , 107 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > levels [ 1 ] ) ;
2010-07-20 17:08:13 +03:00
2023-04-05 02:26:29 +02:00
costIcon = std : : make_shared < CAnimImage > ( " RESOURCE " , GameResID ( EGameResID : : GOLD ) , 0 , 210 , 210 ) ;
2022-11-26 23:12:20 +02:00
cost = std : : make_shared < CLabel > ( 230 , 267 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , " 2000 " ) ;
2010-07-20 17:08:13 +03:00
std : : string hoverText = CGI - > generaltexth - > allTexts [ 609 ] ;
2023-01-01 22:20:41 +02:00
boost : : replace_first ( hoverText , " %s " , CGI - > generaltexth - > levels [ 0 ] + " " + CGI - > skillh - > getByIndex ( SKILL ) - > getNameTranslated ( ) ) ;
2012-01-12 18:23:00 +03:00
2010-07-20 17:08:13 +03:00
text = CGI - > generaltexth - > zelp [ 633 ] . second ;
boost : : replace_first ( text , " %s " , CGI - > generaltexth - > levels [ 0 ] ) ;
2023-01-01 22:20:41 +02:00
boost : : replace_first ( text , " %s " , CGI - > skillh - > getByIndex ( SKILL ) - > getNameTranslated ( ) ) ;
2010-07-20 17:08:13 +03:00
boost : : replace_first ( text , " %d " , " 2000 " ) ;
2023-04-28 13:22:03 +02:00
confirm = std : : make_shared < CButton > ( Point ( 148 , 299 ) , " IBY6432.DEF " , CButton : : tooltip ( hoverText , text ) , [ = ] ( ) { makeDeal ( SKILL ) ; } , EShortcut : : GLOBAL_ACCEPT ) ;
2010-07-20 17:08:13 +03:00
confirm - > block ( ! available ) ;
2012-01-12 18:23:00 +03:00
2023-04-27 19:21:06 +02:00
cancel = std : : make_shared < CButton > ( Point ( 252 , 299 ) , " ICANCEL.DEF " , CGI - > generaltexth - > zelp [ 631 ] , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_CANCEL ) ;
2022-11-29 17:07:21 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2010-07-20 17:08:13 +03:00
}
void CUnivConfirmWindow : : makeDeal ( int skill )
{
2018-04-07 13:34:11 +02:00
owner - > makeDeal ( skill ) ;
2012-06-15 20:08:19 +03:00
close ( ) ;
2010-07-20 17:08:13 +03:00
}
2018-04-07 13:34:11 +02:00
CGarrisonWindow : : CGarrisonWindow ( const CArmedInstance * up , const CGHeroInstance * down , bool removableUnits )
: CWindowObject ( PLAYER_COLORED , " GARRISON " )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
garr = std : : make_shared < CGarrisonInt > ( 92 , 127 , 4 , Point ( 0 , 96 ) , up , down , removableUnits ) ;
{
auto split = std : : make_shared < CButton > ( Point ( 88 , 314 ) , " IDV6432.DEF " , CButton : : tooltip ( CGI - > generaltexth - > tcommands [ 3 ] , " " ) , [ & ] ( ) { garr - > splitClick ( ) ; } ) ;
garr - > addSplitBtn ( split ) ;
}
2023-04-28 13:22:03 +02:00
quit = std : : make_shared < CButton > ( Point ( 399 , 314 ) , " IOK6432.DEF " , CButton : : tooltip ( CGI - > generaltexth - > tcommands [ 8 ] , " " ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_ACCEPT ) ;
2018-04-07 13:34:11 +02:00
std : : string titleText ;
if ( down - > tempOwner = = up - > tempOwner )
{
titleText = CGI - > generaltexth - > allTexts [ 709 ] ;
}
else
{
//assume that this is joining monsters dialog
if ( up - > Slots ( ) . size ( ) > 0 )
{
titleText = CGI - > generaltexth - > allTexts [ 35 ] ;
2023-01-02 18:00:51 +02:00
boost : : algorithm : : replace_first ( titleText , " %s " , up - > Slots ( ) . begin ( ) - > second - > type - > getNamePluralTranslated ( ) ) ;
2018-04-07 13:34:11 +02:00
}
else
{
logGlobal - > error ( " Invalid armed instance for garrison window. " ) ;
}
}
2022-11-26 23:12:20 +02:00
title = std : : make_shared < CLabel > ( 275 , 30 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , titleText ) ;
2018-04-07 13:34:11 +02:00
banner = std : : make_shared < CAnimImage > ( " CREST58 " , up - > getOwner ( ) . getNum ( ) , 0 , 28 , 124 ) ;
portrait = std : : make_shared < CAnimImage > ( " PortraitsLarge " , down - > portrait , 0 , 29 , 222 ) ;
}
void CGarrisonWindow : : updateGarrisons ( )
{
garr - > recreateSlots ( ) ;
}
CHillFortWindow : : CHillFortWindow ( const CGHeroInstance * visitor , const CGObjectInstance * object )
2018-10-29 15:12:07 +02:00
: CStatusbarWindow ( PLAYER_COLORED , " APHLFTBK " ) ,
2012-06-15 20:08:19 +03:00
fort ( object ) ,
2015-01-18 19:23:23 +02:00
hero ( visitor )
2010-07-22 03:32:45 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2012-01-12 18:23:00 +03:00
2022-11-26 23:12:20 +02:00
title = std : : make_shared < CLabel > ( 325 , 32 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , fort - > getObjectName ( ) ) ;
2010-07-22 03:32:45 +03:00
2018-04-07 13:34:11 +02:00
heroPic = std : : make_shared < CHeroArea > ( 30 , 60 , hero ) ;
2012-01-12 18:23:00 +03:00
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < resCount ; i + + )
2016-10-16 06:51:07 +02:00
{
2018-04-07 13:34:11 +02:00
totalIcons [ i ] = std : : make_shared < CAnimImage > ( " SMALRES " , i , 0 , 104 + 76 * i , 237 ) ;
2022-11-26 23:12:20 +02:00
totalLabels [ i ] = std : : make_shared < CLabel > ( 166 + 76 * i , 253 , FONT_SMALL , ETextAlignment : : BOTTOMRIGHT ) ;
2016-10-16 06:51:07 +02:00
}
2014-08-03 14:16:19 +03:00
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < slotsCount ; i + + )
2010-07-22 03:32:45 +03:00
{
2023-04-27 23:29:16 +02:00
upgrade [ i ] = std : : make_shared < CButton > ( Point ( 107 + i * 76 , 171 ) , " " , CButton : : tooltip ( getTextForSlot ( SlotID ( i ) ) ) , [ = ] ( ) { makeDeal ( SlotID ( i ) ) ; } , vstd : : next ( EShortcut : : SELECT_INDEX_1 , i ) ) ;
2018-04-07 13:34:11 +02:00
for ( auto image : { " APHLF1R.DEF " , " APHLF1Y.DEF " , " APHLF1G.DEF " } )
2014-08-03 14:16:19 +03:00
upgrade [ i ] - > addImage ( image ) ;
2016-10-16 06:51:07 +02:00
for ( int j : { 0 , 1 } )
{
2018-04-07 13:34:11 +02:00
slotIcons [ i ] [ j ] = std : : make_shared < CAnimImage > ( " SMALRES " , 0 , 0 , 104 + 76 * i , 128 + 20 * j ) ;
2022-11-26 23:12:20 +02:00
slotLabels [ i ] [ j ] = std : : make_shared < CLabel > ( 168 + 76 * i , 144 + 20 * j , FONT_SMALL , ETextAlignment : : BOTTOMRIGHT ) ;
2016-10-16 06:51:07 +02:00
}
2010-07-22 03:32:45 +03:00
}
2014-10-30 11:00:29 +02:00
2023-04-27 19:21:06 +02:00
upgradeAll = std : : make_shared < CButton > ( Point ( 30 , 231 ) , " " , CButton : : tooltip ( CGI - > generaltexth - > allTexts [ 432 ] ) , [ & ] ( ) { makeDeal ( SlotID ( slotsCount ) ) ; } , EShortcut : : RECRUITMENT_UPGRADE_ALL ) ;
2018-04-07 13:34:11 +02:00
for ( auto image : { " APHLF4R.DEF " , " APHLF4Y.DEF " , " APHLF4G.DEF " } )
2014-08-03 14:16:19 +03:00
upgradeAll - > addImage ( image ) ;
2023-04-28 13:22:03 +02:00
quit = std : : make_shared < CButton > ( Point ( 294 , 275 ) , " IOKAY.DEF " , CButton : : tooltip ( ) , std : : bind ( & CHillFortWindow : : close , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2022-11-29 17:07:21 +02:00
statusbar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2010-08-27 19:20:35 +03:00
2018-04-07 13:34:11 +02:00
garr = std : : make_shared < CGarrisonInt > ( 108 , 60 , 18 , Point ( ) , hero , nullptr ) ;
2010-07-22 03:32:45 +03:00
updateGarrisons ( ) ;
}
void CHillFortWindow : : updateGarrisons ( )
{
2016-10-16 06:51:07 +02:00
std : : array < TResources , slotsCount > costs ; // costs [slot ID] [resource ID] = resource count for upgrade
2023-03-17 01:19:04 +02:00
TResources totalSum ; // totalSum[resource ID] = value
2012-01-12 18:23:00 +03:00
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < slotsCount ; i + + )
2010-07-22 03:32:45 +03:00
{
2023-03-31 12:31:48 +02:00
std : : fill ( costs [ i ] . begin ( ) , costs [ i ] . end ( ) , 0 ) ;
2013-02-16 17:03:47 +03:00
int newState = getState ( SlotID ( i ) ) ;
2018-04-07 13:34:11 +02:00
if ( newState ! = - 1 )
2010-07-22 03:32:45 +03:00
{
2011-05-03 06:14:18 +03:00
UpgradeInfo info ;
2022-12-25 14:03:43 +02:00
LOCPLINT - > cb - > fillUpgradeInfo ( hero , SlotID ( i ) , info ) ;
2018-04-07 13:34:11 +02:00
if ( info . newID . size ( ) ) //we have upgrades here - update costs
2011-07-05 09:14:07 +03:00
{
2013-02-16 17:03:47 +03:00
costs [ i ] = info . cost [ 0 ] * hero - > getStackCount ( SlotID ( i ) ) ;
2023-03-17 01:19:04 +02:00
totalSum + = costs [ i ] ;
2011-07-05 09:14:07 +03:00
}
2010-07-22 03:32:45 +03:00
}
2012-01-12 18:23:00 +03:00
2011-02-20 11:24:53 +02:00
currState [ i ] = newState ;
2015-01-07 12:10:48 +02:00
upgrade [ i ] - > setIndex ( currState [ i ] = = - 1 ? 0 : currState [ i ] ) ;
2011-02-20 11:24:53 +02:00
upgrade [ i ] - > block ( currState [ i ] = = - 1 ) ;
2014-08-03 14:16:19 +03:00
upgrade [ i ] - > addHoverText ( CButton : : NORMAL , getTextForSlot ( SlotID ( i ) ) ) ;
2010-07-22 03:32:45 +03:00
}
2012-01-12 18:23:00 +03:00
2016-10-16 06:51:07 +02:00
//"Upgrade all" slot
int newState = 2 ;
{
TResources myRes = LOCPLINT - > cb - > getResourceAmount ( ) ;
bool allUpgraded = true ; //All creatures are upgraded?
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < slotsCount ; i + + )
allUpgraded & = currState [ i ] = = 1 | | currState [ i ] = = - 1 ;
2016-10-16 06:51:07 +02:00
2018-04-07 13:34:11 +02:00
if ( allUpgraded )
2016-10-16 06:51:07 +02:00
newState = 1 ;
2023-03-17 01:19:04 +02:00
if ( ! totalSum . canBeAfforded ( myRes ) )
2016-10-16 06:51:07 +02:00
newState = 0 ;
}
2011-02-20 11:24:53 +02:00
currState [ slotsCount ] = newState ;
upgradeAll - > setIndex ( newState ) ;
2016-10-16 06:51:07 +02:00
2018-04-07 13:34:11 +02:00
garr - > recreateSlots ( ) ;
2016-10-16 06:51:07 +02:00
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < slotsCount ; i + + )
2016-10-16 06:51:07 +02:00
{
//hide all first
for ( int j : { 0 , 1 } )
{
slotIcons [ i ] [ j ] - > visible = false ;
slotLabels [ i ] [ j ] - > setText ( " " ) ;
}
//if can upgrade or can not afford, draw cost
2018-04-07 13:34:11 +02:00
if ( currState [ i ] = = 0 | | currState [ i ] = = 2 )
2016-10-16 06:51:07 +02:00
{
2018-04-07 13:34:11 +02:00
if ( costs [ i ] . nonZero ( ) )
2016-10-16 06:51:07 +02:00
{
//reverse iterator is used to display gold as first element
int j = 0 ;
2020-10-01 10:38:06 +02:00
for ( int res = ( int ) costs [ i ] . size ( ) - 1 ; ( res > = 0 ) & & ( j < 2 ) ; res - - )
2016-10-16 06:51:07 +02:00
{
int val = costs [ i ] [ res ] ;
if ( ! val )
continue ;
slotIcons [ i ] [ j ] - > visible = true ;
slotIcons [ i ] [ j ] - > setFrame ( res ) ;
2023-03-09 15:36:46 +02:00
slotLabels [ i ] [ j ] - > setText ( std : : to_string ( val ) ) ;
2016-10-16 06:51:07 +02:00
j + + ;
}
}
else //free upgrade - print gold image and "Free" text
{
slotIcons [ i ] [ 0 ] - > visible = true ;
2023-04-05 02:26:29 +02:00
slotIcons [ i ] [ 0 ] - > setFrame ( GameResID ( EGameResID : : GOLD ) ) ;
2016-10-16 06:51:07 +02:00
slotLabels [ i ] [ 0 ] - > setText ( CGI - > generaltexth - > allTexts [ 344 ] ) ;
}
}
}
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < resCount ; i + + )
2016-10-16 06:51:07 +02:00
{
2023-03-17 01:19:04 +02:00
if ( totalSum [ i ] = = 0 )
2016-10-16 06:51:07 +02:00
{
totalIcons [ i ] - > visible = false ;
totalLabels [ i ] - > setText ( " " ) ;
}
else
{
totalIcons [ i ] - > visible = true ;
2023-03-17 01:19:04 +02:00
totalLabels [ i ] - > setText ( std : : to_string ( totalSum [ i ] ) ) ;
2016-10-16 06:51:07 +02:00
}
}
2010-07-22 03:32:45 +03:00
}
2013-02-16 17:03:47 +03:00
void CHillFortWindow : : makeDeal ( SlotID slot )
2010-07-22 03:32:45 +03:00
{
2013-02-16 17:03:47 +03:00
assert ( slot . getNum ( ) > = 0 ) ;
int offset = ( slot . getNum ( ) = = slotsCount ) ? 2 : 0 ;
2018-04-07 13:34:11 +02:00
switch ( currState [ slot . getNum ( ) ] )
2010-07-22 03:32:45 +03:00
{
case 0 :
2018-04-07 13:34:11 +02:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 314 + offset ] , std : : vector < std : : shared_ptr < CComponent > > ( ) , soundBase : : sound_todo ) ;
2010-07-22 03:32:45 +03:00
break ;
case 1 :
2018-04-07 13:34:11 +02:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 313 + offset ] , std : : vector < std : : shared_ptr < CComponent > > ( ) , soundBase : : sound_todo ) ;
2010-07-22 03:32:45 +03:00
break ;
case 2 :
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < slotsCount ; i + + )
{
if ( slot . getNum ( ) = = i | | ( slot . getNum ( ) = = slotsCount & & currState [ i ] = = 2 ) ) //this is activated slot or "upgrade all"
2010-07-22 03:32:45 +03:00
{
2011-05-03 06:14:18 +03:00
UpgradeInfo info ;
2022-12-25 14:03:43 +02:00
LOCPLINT - > cb - > fillUpgradeInfo ( hero , SlotID ( i ) , info ) ;
2013-02-16 17:03:47 +03:00
LOCPLINT - > cb - > upgradeCreature ( hero , SlotID ( i ) , info . newID [ 0 ] ) ;
2010-07-22 03:32:45 +03:00
}
2018-04-07 13:34:11 +02:00
}
2010-07-22 03:32:45 +03:00
break ;
}
}
2013-02-16 17:03:47 +03:00
std : : string CHillFortWindow : : getTextForSlot ( SlotID slot )
2010-07-27 02:20:21 +03:00
{
2018-04-07 13:34:11 +02:00
if ( ! hero - > getCreature ( slot ) ) //we don`t have creature here
2010-07-27 02:20:21 +03:00
return " " ;
std : : string str = CGI - > generaltexth - > allTexts [ 318 ] ;
2010-11-27 03:46:19 +02:00
int amount = hero - > getStackCount ( slot ) ;
2018-04-07 13:34:11 +02:00
if ( amount = = 1 )
2023-01-02 18:00:51 +02:00
boost : : algorithm : : replace_first ( str , " %s " , hero - > getCreature ( slot ) - > getNameSingularTranslated ( ) ) ;
2010-07-27 02:20:21 +03:00
else
2023-01-02 18:00:51 +02:00
boost : : algorithm : : replace_first ( str , " %s " , hero - > getCreature ( slot ) - > getNamePluralTranslated ( ) ) ;
2012-01-12 18:23:00 +03:00
2010-07-27 02:20:21 +03:00
return str ;
}
2013-02-16 17:03:47 +03:00
int CHillFortWindow : : getState ( SlotID slot )
2010-07-22 03:32:45 +03:00
{
2011-07-05 09:14:07 +03:00
TResources myRes = LOCPLINT - > cb - > getResourceAmount ( ) ;
2010-07-22 03:32:45 +03:00
2018-04-07 13:34:11 +02:00
if ( hero - > slotEmpty ( slot ) ) //no creature here
2010-07-22 03:32:45 +03:00
return - 1 ;
2012-01-12 18:23:00 +03:00
2011-05-03 06:14:18 +03:00
UpgradeInfo info ;
2022-12-25 14:03:43 +02:00
LOCPLINT - > cb - > fillUpgradeInfo ( hero , slot , info ) ;
2018-04-07 13:34:11 +02:00
if ( ! info . newID . size ( ) ) //already upgraded
2010-07-22 03:32:45 +03:00
return 1 ;
2011-07-05 09:14:07 +03:00
if ( ! ( info . cost [ 0 ] * hero - > getStackCount ( slot ) ) . canBeAfforded ( myRes ) )
2018-04-07 13:34:11 +02:00
return 0 ;
2011-07-05 09:14:07 +03:00
2010-07-22 03:32:45 +03:00
return 2 ; //can upgrade
}
2012-06-15 20:08:19 +03:00
CThievesGuildWindow : : CThievesGuildWindow ( const CGObjectInstance * _owner ) :
2018-10-29 15:12:07 +02:00
CStatusbarWindow ( PLAYER_COLORED | BORDERED , " TpRank " ) ,
2012-06-15 20:08:19 +03:00
owner ( _owner )
2010-01-31 20:41:22 +02:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2010-02-07 17:06:14 +02:00
2010-02-01 19:51:33 +02:00
SThievesGuildInfo tgi ; //info to be displayed
LOCPLINT - > cb - > getThievesGuildInfo ( tgi , owner ) ;
2023-04-27 19:21:06 +02:00
exitb = std : : make_shared < CButton > ( Point ( 748 , 556 ) , " TPMAGE1 " , CButton : : tooltip ( CGI - > generaltexth - > allTexts [ 600 ] ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_RETURN ) ;
2018-10-29 15:12:07 +02:00
statusbar = CGStatusBar : : create ( 3 , 555 , " TStatBar.bmp " , 742 ) ;
2010-01-31 20:41:22 +02:00
2018-04-07 13:34:11 +02:00
resdatabar = std : : make_shared < CMinorResDataBar > ( ) ;
resdatabar - > moveBy ( pos . topLeft ( ) , true ) ;
2010-02-04 20:40:40 +02:00
2012-06-15 20:08:19 +03:00
//data for information table:
// fields[row][column] = list of id's of players for this box
2013-03-03 20:06:03 +03:00
static std : : vector < std : : vector < PlayerColor > > SThievesGuildInfo : : * fields [ ] =
2012-06-15 20:08:19 +03:00
{ & SThievesGuildInfo : : numOfTowns , & SThievesGuildInfo : : numOfHeroes , & SThievesGuildInfo : : gold ,
& SThievesGuildInfo : : woodOre , & SThievesGuildInfo : : mercSulfCrystGems , & SThievesGuildInfo : : obelisks ,
& SThievesGuildInfo : : artifacts , & SThievesGuildInfo : : army , & SThievesGuildInfo : : income } ;
2010-01-31 20:41:22 +02:00
for ( int g = 0 ; g < 12 ; + + g )
{
2012-06-15 20:08:19 +03:00
int posY [ ] = { 400 , 460 , 510 } ;
2010-01-31 20:41:22 +02:00
int y ;
2012-06-15 20:08:19 +03:00
if ( g < 9 )
2010-01-31 20:41:22 +02:00
y = 52 + 32 * g ;
2012-06-15 20:08:19 +03:00
else
y = posY [ g - 9 ] ;
2010-07-26 01:47:59 +03:00
std : : string text = CGI - > generaltexth - > jktexts [ 24 + g ] ;
boost : : algorithm : : trim_if ( text , boost : : algorithm : : is_any_of ( " \" " ) ) ;
2022-11-26 23:12:20 +02:00
rowHeaders . push_back ( std : : make_shared < CLabel > ( 135 , y , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW , text ) ) ;
2010-01-31 20:41:22 +02:00
}
2018-04-07 13:34:11 +02:00
auto PRSTRIPS = std : : make_shared < CAnimation > ( " PRSTRIPS " ) ;
PRSTRIPS - > preload ( ) ;
2012-06-15 20:08:19 +03:00
for ( int g = 1 ; g < tgi . playerColors . size ( ) ; + + g )
2018-04-07 13:34:11 +02:00
columnBackgrounds . push_back ( std : : make_shared < CAnimImage > ( PRSTRIPS , g - 1 , 0 , 250 + 66 * g , 7 ) ) ;
2010-02-01 19:51:33 +02:00
for ( int g = 0 ; g < tgi . playerColors . size ( ) ; + + g )
2022-11-26 23:12:20 +02:00
columnHeaders . push_back ( std : : make_shared < CLabel > ( 283 + 66 * g , 24 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > jktexts [ 16 + g ] ) ) ;
2018-04-07 13:34:11 +02:00
auto itgflags = std : : make_shared < CAnimation > ( " itgflags " ) ;
itgflags - > preload ( ) ;
2010-02-04 20:40:40 +02:00
//printing flags
2023-04-11 00:29:36 +02:00
for ( int g = 0 ; g < std : : size ( fields ) ; + + g ) //by lines
2010-02-04 20:40:40 +02:00
{
for ( int b = 0 ; b < ( tgi . * fields [ g ] ) . size ( ) ; + + b ) //by places (1st, 2nd, ...)
{
2013-03-03 20:06:03 +03:00
std : : vector < PlayerColor > & players = ( tgi . * fields [ g ] ) [ b ] ; //get players with this place in this line
2012-06-15 20:08:19 +03:00
//position of box
int xpos = 259 + 66 * b ;
int ypos = 41 + 32 * g ;
2010-02-04 20:40:40 +02:00
2012-06-15 20:08:19 +03:00
size_t rowLength [ 2 ] ; //size of each row
rowLength [ 0 ] = std : : min < size_t > ( players . size ( ) , 4 ) ;
rowLength [ 1 ] = players . size ( ) - rowLength [ 0 ] ;
2018-04-07 13:34:11 +02:00
for ( size_t j = 0 ; j < 2 ; j + + )
2010-02-04 20:40:40 +02:00
{
2012-06-15 20:08:19 +03:00
// origin of this row | offset for 2nd row| shift right for short rows
2012-11-11 00:56:19 +03:00
//if we have 2 rows, start either from mid or beginning (depending on count), otherwise center the flags
2020-10-01 10:38:06 +02:00
int rowStartX = xpos + ( j ? 6 + ( ( int ) rowLength [ j ] < 3 ? 12 : 0 ) : 24 - 6 * ( int ) rowLength [ j ] ) ;
2018-04-07 13:34:11 +02:00
int rowStartY = ypos + ( j ? 4 : 0 ) ;
2012-06-15 20:08:19 +03:00
2018-04-07 13:34:11 +02:00
for ( size_t i = 0 ; i < rowLength [ j ] ; i + + )
2020-10-01 10:38:06 +02:00
cells . push_back ( std : : make_shared < CAnimImage > ( itgflags , players [ i + j * 4 ] . getNum ( ) , 0 , rowStartX + ( int ) i * 12 , rowStartY ) ) ;
2010-02-04 20:40:40 +02:00
}
}
}
2012-06-15 20:08:19 +03:00
static const std : : string colorToBox [ ] = { " PRRED.BMP " , " PRBLUE.BMP " , " PRTAN.BMP " , " PRGREEN.BMP " , " PRORANGE.BMP " , " PRPURPLE.BMP " , " PRTEAL.BMP " , " PRROSE.bmp " } ;
2010-02-04 20:40:40 +02:00
2012-06-15 20:08:19 +03:00
//printing best hero
2010-02-04 20:40:40 +02:00
int counter = 0 ;
2013-06-29 16:05:48 +03:00
for ( auto & iter : tgi . colorToBestHero )
2010-02-04 20:40:40 +02:00
{
2018-04-07 13:34:11 +02:00
banners . push_back ( std : : make_shared < CPicture > ( colorToBox [ iter . first . getNum ( ) ] , 253 + 66 * counter , 334 ) ) ;
2012-06-15 20:08:19 +03:00
if ( iter . second . portrait > = 0 )
2010-02-07 19:56:06 +02:00
{
2018-04-07 13:34:11 +02:00
bestHeroes . push_back ( std : : make_shared < CAnimImage > ( " PortraitsSmall " , iter . second . portrait , 0 , 260 + 66 * counter , 360 ) ) ;
2012-06-15 20:08:19 +03:00
//TODO: r-click info:
// - r-click on hero
// - r-click on primary skill label
if ( iter . second . details )
2010-02-07 19:56:06 +02:00
{
2018-04-07 13:34:11 +02:00
primSkillHeaders . push_back ( std : : make_shared < CTextBox > ( CGI - > generaltexth - > allTexts [ 184 ] , Rect ( 260 + 66 * counter , 396 , 52 , 64 ) ,
2022-11-26 23:12:20 +02:00
0 , FONT_TINY , ETextAlignment : : TOPLEFT , Colors : : WHITE ) ) ;
2018-04-07 13:34:11 +02:00
for ( int i = 0 ; i < iter . second . details - > primskills . size ( ) ; + + i )
2012-06-15 20:08:19 +03:00
{
2022-11-26 23:12:20 +02:00
primSkillValues . push_back ( std : : make_shared < CLabel > ( 310 + 66 * counter , 407 + 11 * i , FONT_TINY , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE ,
2023-03-09 15:36:46 +02:00
std : : to_string ( iter . second . details - > primskills [ i ] ) ) ) ;
2012-06-15 20:08:19 +03:00
}
2010-02-07 19:56:06 +02:00
}
}
2012-06-15 20:08:19 +03:00
counter + + ;
2010-02-04 20:40:40 +02:00
}
2010-02-06 15:49:14 +02:00
//printing best creature
counter = 0 ;
2013-06-29 16:05:48 +03:00
for ( auto & it : tgi . bestCreature )
2010-02-06 15:49:14 +02:00
{
2012-06-15 20:08:19 +03:00
if ( it . second > = 0 )
2018-04-07 13:34:11 +02:00
bestCreatures . push_back ( std : : make_shared < CAnimImage > ( " TWCRPORT " , it . second + 2 , 0 , 255 + 66 * counter , 479 ) ) ;
2010-02-06 15:49:14 +02:00
counter + + ;
}
2010-02-07 19:56:06 +02:00
//printing personality
counter = 0 ;
2013-06-29 16:05:48 +03:00
for ( auto & it : tgi . personality )
2010-02-07 19:56:06 +02:00
{
2012-06-15 20:08:19 +03:00
std : : string text ;
2015-01-18 19:23:23 +02:00
if ( it . second = = EAiTactic : : NONE )
{
2012-06-15 20:08:19 +03:00
text = CGI - > generaltexth - > arraytxt [ 172 ] ;
2015-01-18 19:23:23 +02:00
}
else if ( it . second ! = EAiTactic : : RANDOM )
{
text = CGI - > generaltexth - > arraytxt [ 168 + it . second ] ;
}
2010-02-07 19:56:06 +02:00
2022-11-26 23:12:20 +02:00
personalities . push_back ( std : : make_shared < CLabel > ( 283 + 66 * counter , 459 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , text ) ) ;
2010-02-07 19:56:06 +02:00
counter + + ;
}
2010-01-31 20:41:22 +02:00
}
2018-04-07 13:34:11 +02:00
CObjectListWindow : : CItem : : CItem ( CObjectListWindow * _parent , size_t _id , std : : string _text )
2023-01-23 14:43:55 +02:00
: CIntObject ( LCLICK | DOUBLECLICK ) ,
2014-07-13 18:39:45 +03:00
parent ( _parent ) ,
index ( _id )
2010-07-13 08:25:40 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
border = std : : make_shared < CPicture > ( " TPGATES " ) ;
2014-07-13 18:39:45 +03:00
pos = border - > pos ;
2018-04-07 13:34:11 +02:00
2023-07-03 18:24:12 +02:00
setRedrawParent ( true ) ;
2010-01-31 20:41:22 +02:00
2022-11-26 23:12:20 +02:00
text = std : : make_shared < CLabel > ( pos . w / 2 , pos . h / 2 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , _text ) ;
2014-07-13 18:39:45 +03:00
select ( index = = parent - > selected ) ;
2010-07-13 08:25:40 +03:00
}
2010-01-31 20:41:22 +02:00
2014-07-13 18:39:45 +03:00
void CObjectListWindow : : CItem : : select ( bool on )
2011-05-25 16:11:03 +03:00
{
2018-04-07 13:34:11 +02:00
ui8 mask = UPDATE | SHOWALL ;
if ( on )
border - > recActions | = mask ;
2014-07-13 18:39:45 +03:00
else
2018-04-07 13:34:11 +02:00
border - > recActions & = ~ mask ;
redraw ( ) ; //???
2011-05-25 16:11:03 +03:00
}
2023-07-09 16:48:25 +02:00
void CObjectListWindow : : CItem : : clickPressed ( const Point & cursorPosition )
2011-12-22 16:05:19 +03:00
{
2023-07-08 13:33:04 +02:00
parent - > changeSelection ( index ) ;
2011-12-22 16:05:19 +03:00
}
2023-07-08 13:33:04 +02:00
void CObjectListWindow : : CItem : : clickDouble ( const Point & cursorPosition )
2023-01-23 14:43:55 +02:00
{
parent - > elementSelected ( ) ;
}
2022-10-01 09:33:48 +02:00
CObjectListWindow : : CObjectListWindow ( const std : : vector < int > & _items , std : : shared_ptr < CIntObject > titleWidget_ , std : : string _title , std : : string _descr , std : : function < void ( int ) > Callback , size_t initialSelection )
2018-04-07 13:34:11 +02:00
: CWindowObject ( PLAYER_COLORED , " TPGATE " ) ,
2016-11-25 18:58:52 +02:00
onSelect ( Callback ) ,
2022-10-01 09:33:48 +02:00
selected ( initialSelection )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:39:45 +03:00
items . reserve ( _items . size ( ) ) ;
2023-02-10 17:26:31 +02:00
2014-07-13 18:39:45 +03:00
for ( int id : _items )
{
2023-02-10 17:26:31 +02:00
items . push_back ( std : : make_pair ( id , LOCPLINT - > cb - > getObjInstance ( ObjectInstanceID ( id ) ) - > getObjectName ( ) ) ) ;
2014-07-13 18:39:45 +03:00
}
2011-12-22 16:05:19 +03:00
2018-04-07 13:34:11 +02:00
init ( titleWidget_ , _title , _descr ) ;
2011-12-22 16:05:19 +03:00
}
2022-10-01 09:33:48 +02:00
CObjectListWindow : : CObjectListWindow ( const std : : vector < std : : string > & _items , std : : shared_ptr < CIntObject > titleWidget_ , std : : string _title , std : : string _descr , std : : function < void ( int ) > Callback , size_t initialSelection )
2018-04-07 13:34:11 +02:00
: CWindowObject ( PLAYER_COLORED , " TPGATE " ) ,
2016-11-25 18:58:52 +02:00
onSelect ( Callback ) ,
2022-10-01 09:33:48 +02:00
selected ( initialSelection )
2012-12-11 15:12:46 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 18:39:45 +03:00
items . reserve ( _items . size ( ) ) ;
2018-04-07 13:34:11 +02:00
for ( size_t i = 0 ; i < _items . size ( ) ; i + + )
2014-07-13 18:39:45 +03:00
items . push_back ( std : : make_pair ( int ( i ) , _items [ i ] ) ) ;
2012-12-11 15:12:46 +03:00
2018-04-07 13:34:11 +02:00
init ( titleWidget_ , _title , _descr ) ;
2012-12-11 15:12:46 +03:00
}
2018-04-07 13:34:11 +02:00
void CObjectListWindow : : init ( std : : shared_ptr < CIntObject > titleWidget_ , std : : string _title , std : : string _descr )
2012-06-13 16:04:06 +03:00
{
2018-04-07 13:34:11 +02:00
titleWidget = titleWidget_ ;
2012-06-13 16:04:06 +03:00
2022-11-26 23:12:20 +02:00
title = std : : make_shared < CLabel > ( 152 , 27 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , _title ) ;
descr = std : : make_shared < CLabel > ( 145 , 133 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , _descr ) ;
2023-04-27 19:21:06 +02:00
exit = std : : make_shared < CButton > ( Point ( 228 , 402 ) , " ICANCEL.DEF " , CButton : : tooltip ( ) , std : : bind ( & CObjectListWindow : : exitPressed , this ) , EShortcut : : GLOBAL_CANCEL ) ;
2012-06-13 16:04:06 +03:00
2018-04-07 13:34:11 +02:00
if ( titleWidget )
2014-07-13 18:39:45 +03:00
{
2018-04-07 13:34:11 +02:00
addChild ( titleWidget . get ( ) ) ;
titleWidget - > recActions = 255 - DISPOSE ;
titleWidget - > pos . x = pos . w / 2 + pos . x - titleWidget - > pos . w / 2 ;
titleWidget - > pos . y = 75 + pos . y - titleWidget - > pos . h / 2 ;
2014-07-13 18:39:45 +03:00
}
2018-04-07 13:34:11 +02:00
list = std : : make_shared < CListBox > ( std : : bind ( & CObjectListWindow : : genItem , this , _1 ) ,
2014-07-13 18:39:45 +03:00
Point ( 14 , 151 ) , Point ( 0 , 25 ) , 9 , items . size ( ) , 0 , 1 , Rect ( 262 , - 32 , 256 , 256 ) ) ;
2023-07-03 18:24:12 +02:00
list - > setRedrawParent ( true ) ;
2020-10-02 23:55:46 +02:00
2023-04-28 13:22:03 +02:00
ok = std : : make_shared < CButton > ( Point ( 15 , 402 ) , " IOKAY.DEF " , CButton : : tooltip ( ) , std : : bind ( & CObjectListWindow : : elementSelected , this ) , EShortcut : : GLOBAL_ACCEPT ) ;
2020-10-02 23:55:46 +02:00
ok - > block ( ! list - > size ( ) ) ;
2012-06-13 16:04:06 +03:00
}
2018-04-07 13:34:11 +02:00
std : : shared_ptr < CIntObject > CObjectListWindow : : genItem ( size_t index )
2012-06-13 16:04:06 +03:00
{
2018-04-07 13:34:11 +02:00
if ( index < items . size ( ) )
return std : : make_shared < CItem > ( this , index , items [ index ] . second ) ;
return std : : shared_ptr < CIntObject > ( ) ;
2012-06-13 16:04:06 +03:00
}
2014-07-13 18:39:45 +03:00
void CObjectListWindow : : elementSelected ( )
2012-06-13 16:04:06 +03:00
{
2014-07-13 18:39:45 +03:00
std : : function < void ( int ) > toCall = onSelect ; //save
int where = items [ selected ] . first ; //required variables
2018-07-25 00:36:48 +02:00
close ( ) ; //then destroy window
2014-07-13 18:39:45 +03:00
toCall ( where ) ; //and send selected object
2012-06-13 16:04:06 +03:00
}
2017-06-06 06:53:51 +02:00
void CObjectListWindow : : exitPressed ( )
{
std : : function < void ( ) > toCall = onExit ; //save
2018-07-25 00:36:48 +02:00
close ( ) ; //then destroy window
2017-06-06 06:53:51 +02:00
if ( toCall )
toCall ( ) ;
}
2014-07-13 18:39:45 +03:00
void CObjectListWindow : : changeSelection ( size_t which )
2012-06-13 16:04:06 +03:00
{
2014-07-13 18:39:45 +03:00
ok - > block ( false ) ;
2018-04-07 13:34:11 +02:00
if ( selected = = which )
2014-07-13 18:39:45 +03:00
return ;
2012-06-13 16:04:06 +03:00
2018-04-07 13:34:11 +02:00
for ( std : : shared_ptr < CIntObject > element : list - > getItems ( ) )
2012-06-13 16:04:06 +03:00
{
2018-04-07 13:34:11 +02:00
CItem * item = dynamic_cast < CItem * > ( element . get ( ) ) ;
if ( item )
2014-07-13 18:39:45 +03:00
{
2018-04-07 13:34:11 +02:00
if ( item - > index = = selected )
2014-07-13 18:39:45 +03:00
item - > select ( false ) ;
2018-04-07 13:34:11 +02:00
if ( item - > index = = which )
2014-07-13 18:39:45 +03:00
item - > select ( true ) ;
}
2012-06-13 16:04:06 +03:00
}
2014-07-13 18:39:45 +03:00
selected = which ;
2012-06-13 16:04:06 +03:00
}
2023-04-27 19:21:06 +02:00
void CObjectListWindow : : keyPressed ( EShortcut key )
2011-12-22 16:05:19 +03:00
{
2020-10-01 10:38:06 +02:00
int sel = static_cast < int > ( selected ) ;
2011-12-22 16:05:19 +03:00
2023-02-02 18:02:25 +02:00
switch ( key )
2014-07-13 18:39:45 +03:00
{
2023-04-28 13:22:03 +02:00
break ; case EShortcut : : MOVE_UP :
2014-07-13 18:39:45 +03:00
sel - = 1 ;
2011-12-22 16:05:19 +03:00
2023-04-28 13:22:03 +02:00
break ; case EShortcut : : MOVE_DOWN :
2014-07-13 18:39:45 +03:00
sel + = 1 ;
2011-12-22 16:05:19 +03:00
2023-04-28 13:22:03 +02:00
break ; case EShortcut : : MOVE_PAGE_UP :
2014-07-13 18:39:45 +03:00
sel - = 9 ;
2011-12-22 16:05:19 +03:00
2023-04-28 13:22:03 +02:00
break ; case EShortcut : : MOVE_PAGE_DOWN :
2014-07-13 18:39:45 +03:00
sel + = 9 ;
2011-12-22 16:05:19 +03:00
2023-04-28 13:22:03 +02:00
break ; case EShortcut : : MOVE_FIRST :
2014-07-13 18:39:45 +03:00
sel = 0 ;
2011-12-22 16:05:19 +03:00
2023-04-28 13:22:03 +02:00
break ; case EShortcut : : MOVE_LAST :
2020-10-01 10:38:06 +02:00
sel = static_cast < int > ( items . size ( ) ) ;
2011-12-22 16:05:19 +03:00
2014-07-13 18:39:45 +03:00
break ; default :
return ;
}
2023-04-11 00:00:46 +02:00
vstd : : abetween < int > ( sel , 0 , items . size ( ) - 1 ) ;
2014-07-13 18:39:45 +03:00
list - > scrollTo ( sel ) ;
changeSelection ( sel ) ;
2011-06-03 06:23:50 +03:00
}