2017-07-13 10:26:03 +02:00
/*
* CCastleInterface . 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-20 12:02:50 +03:00
# include "CCastleInterface.h"
2011-12-14 00:23:17 +03:00
2011-03-22 15:19:07 +02:00
# include "CHeroWindow.h"
2014-07-13 20:53:37 +03:00
# include "CTradeWindow.h"
2022-09-18 14:47:49 +02:00
# include "InfoWindows.h"
2014-07-13 18:39:45 +03:00
# include "GUIClasses.h"
2017-11-01 15:58:49 +02:00
# include "QuickRecruitmentWindow.h"
2023-07-30 14:29:18 +02:00
# include "CCreatureWindow.h"
2011-03-22 15:19:07 +02:00
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
# include "../CMusicHandler.h"
# include "../CPlayerInterface.h"
2023-04-17 01:02:31 +02:00
# include "../PlayerLocalState.h"
2014-07-13 20:53:37 +03:00
# include "../gui/CGuiHandler.h"
2023-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
# include "../widgets/MiscWidgets.h"
2014-07-15 10:14:49 +03:00
# include "../widgets/CComponent.h"
2023-07-07 00:08:29 +02:00
# include "../widgets/CGarrisonInt.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/Buttons.h"
# include "../widgets/TextControls.h"
2023-06-02 15:42:18 +02:00
# include "../render/Canvas.h"
2023-02-01 20:42:06 +02:00
# include "../render/IImage.h"
# include "../render/ColorFilter.h"
2023-05-08 14:18:34 +02:00
# include "../adventureMap/AdventureMapInterface.h"
2023-02-10 16:26:32 +02:00
# include "../adventureMap/CList.h"
# include "../adventureMap/CResDataBar.h"
2014-07-13 20:53:37 +03:00
# include "../../CCallback.h"
# include "../../lib/CArtHandler.h"
# include "../../lib/CBuildingHandler.h"
# include "../../lib/CCreatureHandler.h"
# include "../../lib/CGeneralTextHandler.h"
2023-03-15 21:34:29 +02:00
# include "../../lib/GameSettings.h"
2015-02-02 10:25:26 +02:00
# include "../../lib/spells/CSpellHandler.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/CTownHandler.h"
# include "../../lib/GameConstants.h"
2018-08-11 17:25:09 +02:00
# include "../../lib/StartInfo.h"
2023-06-25 21:28:24 +02:00
# include "../../lib/campaign/CampaignState.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/mapObjects/CGHeroInstance.h"
2014-07-15 10:14:49 +03:00
# include "../../lib/mapObjects/CGTownInstance.h"
2011-03-22 15:19:07 +02:00
2023-01-30 19:55:32 +02:00
2023-02-02 21:54:47 +02:00
static bool useCompactCreatureBox ( )
{
2023-03-05 16:00:36 +02:00
return settings [ " gameTweaks " ] [ " compactTownCreatureInfo " ] . Bool ( ) ;
2023-02-02 21:54:47 +02:00
}
static bool useAvailableAmountAsCreatureLabel ( )
{
2023-03-05 16:00:36 +02:00
return settings [ " gameTweaks " ] [ " availableCreaturesAsDwellingLabel " ] . Bool ( ) ;
2023-02-02 21:54:47 +02:00
}
2018-04-07 13:34:11 +02:00
CBuildingRect : : CBuildingRect ( CCastleBuildings * Par , const CGTownInstance * Town , const CStructure * Str )
2023-01-27 12:22:48 +02:00
: CShowableAnim ( 0 , 0 , Str - > defName , CShowableAnim : : BASE , BUILDING_FRAME_TIME ) ,
2023-01-15 20:56:55 +02:00
parent ( Par ) ,
town ( Town ) ,
str ( Str ) ,
2023-02-20 18:37:33 +02:00
border ( nullptr ) ,
area ( nullptr ) ,
2023-01-16 19:26:31 +02:00
stateTimeCounter ( BUILD_ANIMATION_FINISHED_TIMEPOINT )
2008-08-02 18:08:03 +03:00
{
2023-06-22 21:11:48 +02:00
addUsedEvents ( LCLICK | SHOW_POPUP | MOVE | HOVER | TIME ) ;
2011-03-22 15:19:07 +02:00
pos . x + = str - > pos . x ;
pos . y + = str - > pos . y ;
2010-11-15 17:15:00 +02:00
2023-01-15 20:10:40 +02:00
// special animation frame manipulation for castle shipyard with and without ship
// done due to .def used in special way, not to animate building - first image is for shipyard without citadel moat, 2nd image is for including moat
if ( Town - > town - > faction - > getId ( ) = = FactionID : : CASTLE & & Str - > building & &
( Str - > building - > bid = = BuildingID : : SHIPYARD | | Str - > building - > bid = = BuildingID : : SHIP ) )
{
if ( Town - > hasBuilt ( BuildingID : : CITADEL ) )
{
this - > first = 1 ;
this - > frame = 1 ;
}
else
this - > last = 0 ;
}
2018-04-07 13:34:11 +02:00
if ( ! str - > borderName . empty ( ) )
2023-02-21 15:44:18 +02:00
border = IImage : : createFromFile ( str - > borderName , EImageBlitMode : : ALPHA ) ;
2009-10-13 07:07:26 +03:00
2018-04-07 13:34:11 +02:00
if ( ! str - > areaName . empty ( ) )
2023-02-21 15:44:18 +02:00
area = IImage : : createFromFile ( str - > areaName , EImageBlitMode : : ALPHA ) ;
2008-01-19 13:55:04 +02:00
}
2018-04-07 13:34:11 +02:00
const CBuilding * CBuildingRect : : getBuilding ( )
{
if ( ! str - > building )
return nullptr ;
if ( str - > hiddenUpgrade ) // hidden upgrades, e.g. hordes - return base (dwelling for hordes)
return town - > town - > buildings . at ( str - > building - > getBase ( ) ) ;
return str - > building ;
2008-01-19 13:55:04 +02:00
}
2008-03-23 03:01:17 +02:00
2008-01-19 13:55:04 +02:00
bool CBuildingRect : : operator < ( const CBuildingRect & p2 ) const
{
2012-09-05 15:49:23 +03:00
return ( str - > pos . z ) < ( p2 . str - > pos . z ) ;
2008-01-19 13:55:04 +02:00
}
2011-03-22 15:19:07 +02:00
2008-01-20 18:24:03 +02:00
void CBuildingRect : : hover ( bool on )
2008-01-19 13:55:04 +02:00
{
2023-06-22 21:11:48 +02:00
if ( ! area )
return ;
2008-01-24 00:15:33 +02:00
if ( on )
2008-01-20 18:24:03 +02:00
{
2023-06-22 21:11:48 +02:00
if ( ! parent - > selectedBuilding //no building hovered
| | ( * parent - > selectedBuilding ) < ( * this ) ) //or we are on top
{
parent - > selectedBuilding = this ;
GH . statusbar ( ) - > write ( getSubtitle ( ) ) ;
}
2008-01-24 00:15:33 +02:00
}
2008-08-02 18:08:03 +03:00
else
2008-01-24 00:15:33 +02:00
{
2011-03-22 15:19:07 +02:00
if ( parent - > selectedBuilding = = this )
2008-01-27 22:37:10 +02:00
{
2013-06-26 14:18:27 +03:00
parent - > selectedBuilding = nullptr ;
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2008-01-27 22:37:10 +02:00
}
2008-01-20 18:24:03 +02:00
}
2008-01-19 13:55:04 +02:00
}
2010-11-15 17:15:00 +02:00
2023-07-09 16:48:25 +02:00
void CBuildingRect : : clickPressed ( const Point & cursorPosition )
2008-01-19 13:55:04 +02:00
{
2023-07-08 13:33:04 +02:00
if ( getBuilding ( ) & & area & & ( parent - > selectedBuilding = = this ) )
2021-02-20 03:57:50 +02:00
{
2023-06-22 21:11:48 +02:00
auto building = getBuilding ( ) ;
parent - > buildingClicked ( building - > bid , building - > subId , building - > upgrade ) ;
2021-02-20 03:57:50 +02:00
}
2008-01-19 13:55:04 +02:00
}
2010-11-15 17:15:00 +02:00
2023-07-08 13:33:04 +02:00
void CBuildingRect : : showPopupWindow ( const Point & cursorPosition )
2008-01-19 13:55:04 +02:00
{
2023-06-11 17:20:10 +02:00
if ( ( ! area ) | | ( this ! = parent - > selectedBuilding ) | | getBuilding ( ) = = nullptr )
2008-03-06 20:54:35 +02:00
return ;
2023-06-22 21:11:48 +02:00
BuildingID bid = getBuilding ( ) - > bid ;
const CBuilding * bld = town - > town - > buildings . at ( bid ) ;
if ( bid < BuildingID : : DWELL_FIRST )
2013-12-02 14:58:02 +03:00
{
2023-06-22 21:11:48 +02:00
CRClickPopup : : createAndPush ( CInfoWindow : : genText ( bld - > getNameTranslated ( ) , bld - > getDescriptionTranslated ( ) ) ,
std : : make_shared < CComponent > ( CComponent : : building , bld - > town - > faction - > getIndex ( ) , bld - > bid ) ) ;
}
else
{
int level = ( bid - BuildingID : : DWELL_FIRST ) % GameConstants : : CREATURES_PER_TOWN ;
GH . windows ( ) . createAndPushWindow < CDwellingInfoBox > ( parent - > pos . x + parent - > pos . w / 2 , parent - > pos . y + parent - > pos . h / 2 , town , level ) ;
2008-03-06 20:54:35 +02:00
}
2008-01-19 13:55:04 +02:00
}
2010-06-30 22:27:35 +03:00
2023-06-02 15:42:18 +02:00
void CBuildingRect : : show ( Canvas & to )
2010-11-15 17:15:00 +02:00
{
2023-01-16 01:33:53 +02:00
uint32_t stageDelay = BUILDING_APPEAR_TIMEPOINT ;
2011-03-22 15:19:07 +02:00
2023-01-16 01:33:53 +02:00
if ( stateTimeCounter < BUILDING_APPEAR_TIMEPOINT )
2011-03-22 15:19:07 +02:00
{
2023-01-15 20:56:55 +02:00
setAlpha ( 255 * stateTimeCounter / stageDelay ) ;
2011-03-22 15:19:07 +02:00
CShowableAnim : : show ( to ) ;
}
else
{
setAlpha ( 255 ) ;
CShowableAnim : : show ( to ) ;
}
2023-01-16 01:33:53 +02:00
if ( border & & stateTimeCounter > BUILDING_APPEAR_TIMEPOINT )
2011-03-22 15:19:07 +02:00
{
2023-01-16 01:33:53 +02:00
if ( stateTimeCounter > = BUILD_ANIMATION_FINISHED_TIMEPOINT )
2011-03-22 15:19:07 +02:00
{
2018-04-07 13:34:11 +02:00
if ( parent - > selectedBuilding = = this )
2023-06-02 15:42:18 +02:00
to . draw ( border , pos . topLeft ( ) ) ;
2011-03-22 15:19:07 +02:00
return ;
}
2013-12-08 13:07:06 +03:00
2023-01-30 18:25:47 +02:00
auto darkBorder = ColorFilter : : genRangeShifter ( 0.f , 0.f , 0.f , 0.5f , 0.5f , 0.5f ) ;
auto lightBorder = ColorFilter : : genRangeShifter ( 0.f , 0.f , 0.f , 2.0f , 2.0f , 2.0f ) ;
auto baseBorder = ColorFilter : : genEmptyShifter ( ) ;
2013-12-08 13:07:06 +03:00
2023-01-30 18:25:47 +02:00
float progress = float ( stateTimeCounter % stageDelay ) / stageDelay ;
2013-12-08 13:07:06 +03:00
2023-01-30 18:25:47 +02:00
if ( stateTimeCounter < BUILDING_WHITE_BORDER_TIMEPOINT )
border - > adjustPalette ( ColorFilter : : genInterpolated ( lightBorder , darkBorder , progress ) , 0 ) ;
else
if ( stateTimeCounter < BUILDING_YELLOW_BORDER_TIMEPOINT )
border - > adjustPalette ( ColorFilter : : genInterpolated ( darkBorder , baseBorder , progress ) , 0 ) ;
else
border - > adjustPalette ( baseBorder , 0 ) ;
2023-06-02 15:42:18 +02:00
to . draw ( border , pos . topLeft ( ) ) ;
2011-03-22 15:19:07 +02:00
}
2023-05-13 16:24:18 +02:00
}
2023-01-30 18:25:47 +02:00
2023-05-13 16:24:18 +02:00
void CBuildingRect : : tick ( uint32_t msPassed )
{
CShowableAnim : : tick ( msPassed ) ;
stateTimeCounter + = msPassed ;
2010-11-15 17:15:00 +02:00
}
2023-06-02 15:42:18 +02:00
void CBuildingRect : : showAll ( Canvas & to )
2010-11-15 17:15:00 +02:00
{
2023-01-15 20:56:55 +02:00
if ( stateTimeCounter = = 0 )
2011-02-20 11:24:53 +02:00
return ;
2011-03-22 15:19:07 +02:00
2011-02-06 19:26:27 +02:00
CShowableAnim : : showAll ( to ) ;
2023-05-17 22:22:45 +02:00
if ( ! isActive ( ) & & parent - > selectedBuilding = = this & & border )
2023-06-02 15:42:18 +02:00
to . draw ( border , pos . topLeft ( ) ) ;
2010-11-15 17:15:00 +02:00
}
2013-05-30 21:43:45 +03:00
std : : string CBuildingRect : : getSubtitle ( ) //hover text for building
2010-06-30 22:27:35 +03:00
{
2013-05-30 21:43:45 +03:00
if ( ! getBuilding ( ) )
2012-09-05 15:49:23 +03:00
return " " ;
2013-12-02 14:58:02 +03:00
int bid = getBuilding ( ) - > bid ;
if ( bid < 30 ) //non-dwellings - only buiding name
2023-01-04 15:17:50 +02:00
return town - > town - > buildings . at ( getBuilding ( ) - > bid ) - > getNameTranslated ( ) ;
2013-12-02 14:58:02 +03:00
else //dwellings - recruit %creature%
{
auto & availableCreatures = town - > creatures [ ( bid - 30 ) % GameConstants : : CREATURES_PER_TOWN ] . second ;
if ( availableCreatures . size ( ) )
{
int creaID = availableCreatures . back ( ) ; //taking last of available creatures
2023-01-02 18:00:51 +02:00
return CGI - > generaltexth - > allTexts [ 16 ] + " " + CGI - > creh - > objects . at ( creaID ) - > getNamePluralTranslated ( ) ;
2013-12-02 14:58:02 +03:00
}
else
{
2017-08-11 13:38:10 +02:00
logGlobal - > warn ( " Dwelling with id %d offers no creatures! " , bid ) ;
2013-02-07 18:27:22 +03:00
return " #ERROR# " ;
}
2010-06-30 22:27:35 +03:00
}
}
2023-06-22 21:11:48 +02:00
void CBuildingRect : : mouseMoved ( const Point & cursorPosition , const Point & lastUpdateDistance )
2008-01-24 00:15:33 +02:00
{
2023-06-22 21:11:48 +02:00
hover ( true ) ;
}
bool CBuildingRect : : receiveEvent ( const Point & position , int eventType ) const
{
if ( ! pos . isInside ( position . x , position . y ) )
return false ;
if ( area & & area - > isTransparent ( position - pos . topLeft ( ) ) )
return false ;
return CIntObject : : receiveEvent ( position , eventType ) ;
2008-01-24 00:15:33 +02:00
}
2010-11-15 17:15:00 +02:00
2018-04-07 13:34:11 +02:00
CDwellingInfoBox : : CDwellingInfoBox ( int centerX , int centerY , const CGTownInstance * Town , int level )
: CWindowObject ( RCLICK_POPUP , " CRTOINFO " , Point ( centerX , centerY ) )
2013-12-02 14:58:02 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
background - > colorize ( Town - > tempOwner ) ;
2013-12-02 14:58:02 +03:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const CCreature * creature = CGI - > creh - > objects . at ( Town - > creatures . at ( level ) . second . back ( ) ) ;
2013-12-02 14:58:02 +03:00
2023-01-02 18:00:51 +02:00
title = std : : make_shared < CLabel > ( 80 , 30 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , creature - > getNamePluralTranslated ( ) ) ;
2018-04-07 13:34:11 +02:00
animation = std : : make_shared < CCreaturePic > ( 30 , 44 , creature , true , true ) ;
2014-03-07 16:21:09 +03:00
2023-03-09 15:36:46 +02:00
std : : string text = std : : to_string ( Town - > creatures . at ( level ) . first ) ;
2022-11-26 23:12:20 +02:00
available = std : : make_shared < CLabel > ( 80 , 190 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 217 ] + text ) ;
costPerTroop = std : : make_shared < CLabel > ( 80 , 227 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 346 ] ) ;
2014-03-07 16:21:09 +03:00
2011-12-14 00:23:17 +03:00
for ( int i = 0 ; i < GameConstants : : RESOURCE_QUANTITY ; i + + )
2011-04-07 20:54:08 +03:00
{
2023-04-05 02:26:29 +02:00
auto res = static_cast < EGameResID > ( i ) ;
if ( creature - > getRecruitCost ( res ) )
2011-04-07 20:54:08 +03:00
{
2018-04-07 13:34:11 +02:00
resPicture . push_back ( std : : make_shared < CAnimImage > ( " RESOURCE " , i , 0 , 0 , 0 ) ) ;
2023-04-05 02:26:29 +02:00
resAmount . push_back ( std : : make_shared < CLabel > ( 0 , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , std : : to_string ( creature - > getRecruitCost ( res ) ) ) ) ;
2011-04-07 20:54:08 +03:00
}
}
int posY = 238 ;
2020-10-01 10:38:06 +02:00
int posX = pos . w / 2 - ( int ) resAmount . size ( ) * 25 + 5 ;
2011-04-07 20:54:08 +03:00
for ( size_t i = 0 ; i < resAmount . size ( ) ; i + + )
{
2011-12-22 16:05:19 +03:00
resPicture [ i ] - > moveBy ( Point ( posX , posY ) ) ;
resAmount [ i ] - > moveBy ( Point ( posX + 16 , posY + 43 ) ) ;
2011-09-23 18:58:18 +03:00
posX + = 50 ;
2011-04-07 20:54:08 +03:00
}
}
2018-04-07 13:34:11 +02:00
CDwellingInfoBox : : ~ CDwellingInfoBox ( ) = default ;
CHeroGSlot : : CHeroGSlot ( int x , int y , int updown , const CGHeroInstance * h , HeroSlots * Owner )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
owner = Owner ;
pos . x + = x ;
pos . y + = y ;
pos . w = 58 ;
pos . h = 64 ;
upg = updown ;
portrait = std : : make_shared < CAnimImage > ( " PortraitsLarge " , 0 , 0 , 0 , 0 ) ;
portrait - > visible = false ;
flag = std : : make_shared < CAnimImage > ( " CREST58 " , 0 , 0 , 0 , 0 ) ;
flag - > visible = false ;
selection = std : : make_shared < CAnimImage > ( " TWCRPORT " , 1 , 0 ) ;
selection - > visible = false ;
set ( h ) ;
2023-06-13 18:33:35 +02:00
addUsedEvents ( LCLICK | SHOW_POPUP | HOVER ) ;
2018-04-07 13:34:11 +02:00
}
CHeroGSlot : : ~ CHeroGSlot ( ) = default ;
void CHeroGSlot : : hover ( bool on )
2008-08-16 11:47:41 +03:00
{
2010-11-15 17:15:00 +02:00
if ( ! on )
2009-12-23 03:46:15 +02:00
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2009-12-23 03:46:15 +02:00
return ;
}
2018-04-07 13:34:11 +02:00
std : : shared_ptr < CHeroGSlot > other = upg ? owner - > garrisonedHero : owner - > visitingHero ;
2008-08-16 11:47:41 +03:00
std : : string temp ;
if ( hero )
{
2018-04-07 13:34:11 +02:00
if ( isSelected ( ) ) //view NNN
2008-08-16 11:47:41 +03:00
{
2008-12-22 19:48:41 +02:00
temp = CGI - > generaltexth - > tcommands [ 4 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( temp , " %s " , hero - > getNameTranslated ( ) ) ;
2008-08-16 11:47:41 +03:00
}
2018-04-07 13:34:11 +02:00
else if ( other - > hero & & other - > isSelected ( ) ) //exchange
2008-08-16 11:47:41 +03:00
{
2008-12-22 19:48:41 +02:00
temp = CGI - > generaltexth - > tcommands [ 7 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( temp , " %s " , hero - > getNameTranslated ( ) ) ;
boost : : algorithm : : replace_first ( temp , " %s " , other - > hero - > getNameTranslated ( ) ) ;
2008-08-16 11:47:41 +03:00
}
else // select NNN (in ZZZ)
{
if ( upg ) //down - visiting
{
2008-12-22 19:48:41 +02:00
temp = CGI - > generaltexth - > tcommands [ 32 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( temp , " %s " , hero - > getNameTranslated ( ) ) ;
2008-08-16 11:47:41 +03:00
}
else //up - garrison
{
2008-12-22 19:48:41 +02:00
temp = CGI - > generaltexth - > tcommands [ 12 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( temp , " %s " , hero - > getNameTranslated ( ) ) ;
2008-08-16 11:47:41 +03:00
}
}
}
else //we are empty slot
{
2018-04-07 13:34:11 +02:00
if ( other - > isSelected ( ) & & other - > hero ) //move NNNN
2008-08-16 11:47:41 +03:00
{
2008-12-22 19:48:41 +02:00
temp = CGI - > generaltexth - > tcommands [ 6 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( temp , " %s " , other - > hero - > getNameTranslated ( ) ) ;
2008-08-16 11:47:41 +03:00
}
else //empty
{
temp = CGI - > generaltexth - > allTexts [ 507 ] ;
}
}
if ( temp . size ( ) )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( temp ) ;
2008-08-16 11:47:41 +03:00
}
2009-04-14 15:47:09 +03:00
2023-07-09 16:48:25 +02:00
void CHeroGSlot : : clickPressed ( const Point & cursorPosition )
2008-08-16 11:47:41 +03:00
{
2018-04-07 13:34:11 +02:00
std : : shared_ptr < CHeroGSlot > other = upg ? owner - > garrisonedHero : owner - > visitingHero ;
2009-09-09 09:04:42 +03:00
2023-07-08 13:33:04 +02:00
owner - > garr - > setSplittingMode ( false ) ;
owner - > garr - > selectSlot ( nullptr ) ;
2018-04-07 13:34:11 +02:00
2023-07-08 13:33:04 +02:00
if ( hero & & isSelected ( ) )
{
setHighlight ( false ) ;
LOCPLINT - > openHeroWindow ( hero ) ;
}
else if ( other - > hero & & other - > isSelected ( ) )
{
owner - > swapArmies ( ) ;
2008-08-16 11:47:41 +03:00
}
2023-07-08 13:33:04 +02:00
else if ( hero )
{
setHighlight ( true ) ;
owner - > garr - > selectSlot ( nullptr ) ;
redraw ( ) ;
}
//refresh statusbar
hover ( false ) ;
hover ( true ) ;
2008-08-16 11:47:41 +03:00
}
2009-04-14 15:47:09 +03:00
2023-07-08 13:33:04 +02:00
void CHeroGSlot : : showPopupWindow ( const Point & cursorPosition )
2015-08-24 19:31:03 +02:00
{
2023-06-11 17:20:10 +02:00
if ( hero )
2015-08-24 19:31:03 +02:00
{
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CInfoBoxPopup > ( Point ( pos . x + 175 , pos . y + 100 ) , hero ) ;
2015-08-24 19:31:03 +02:00
}
}
2008-08-16 11:47:41 +03:00
void CHeroGSlot : : deactivate ( )
{
2018-04-07 13:34:11 +02:00
selection - > visible = false ;
2010-11-15 17:15:00 +02:00
CIntObject : : deactivate ( ) ;
2008-08-16 11:47:41 +03:00
}
2009-04-14 15:47:09 +03:00
2018-04-07 13:34:11 +02:00
bool CHeroGSlot : : isSelected ( ) const
2008-08-16 11:47:41 +03:00
{
2018-04-07 13:34:11 +02:00
return selection - > visible ;
2008-08-16 11:47:41 +03:00
}
2009-04-14 15:47:09 +03:00
2018-04-07 13:34:11 +02:00
void CHeroGSlot : : setHighlight ( bool on )
2009-09-09 09:04:42 +03:00
{
2018-04-07 13:34:11 +02:00
selection - > visible = on ;
2012-05-13 18:04:21 +03:00
2011-04-30 21:16:58 +03:00
if ( owner - > garrisonedHero - > hero & & owner - > visitingHero - > hero ) //two heroes in town
2009-09-09 09:04:42 +03:00
{
2013-06-29 16:05:48 +03:00
for ( auto & elem : owner - > garr - > splitButtons ) //splitting enabled when slot higlighted
elem - > block ( ! on ) ;
2009-09-09 09:04:42 +03:00
}
}
2018-04-07 13:34:11 +02:00
void CHeroGSlot : : set ( const CGHeroInstance * newHero )
2012-05-13 18:04:21 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2012-05-13 18:04:21 +03:00
hero = newHero ;
2018-04-07 13:34:11 +02:00
selection - > visible = false ;
portrait - > visible = false ;
flag - > visible = false ;
if ( newHero )
{
portrait - > visible = true ;
portrait - > setFrame ( newHero - > portrait ) ;
}
2012-05-13 18:04:21 +03:00
else if ( ! upg & & owner - > showEmpty ) //up garrison
2018-04-07 13:34:11 +02:00
{
flag - > visible = true ;
flag - > setFrame ( LOCPLINT - > castleInt - > town - > getOwner ( ) . getNum ( ) ) ;
}
}
HeroSlots : : HeroSlots ( const CGTownInstance * Town , Point garrPos , Point visitPos , std : : shared_ptr < CGarrisonInt > Garrison , bool ShowEmpty ) :
showEmpty ( ShowEmpty ) ,
town ( Town ) ,
garr ( Garrison )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
garrisonedHero = std : : make_shared < CHeroGSlot > ( garrPos . x , garrPos . y , 0 , town - > garrisonHero , this ) ;
visitingHero = std : : make_shared < CHeroGSlot > ( visitPos . x , visitPos . y , 1 , town - > visitingHero , this ) ;
}
HeroSlots : : ~ HeroSlots ( ) = default ;
void HeroSlots : : update ( )
{
garrisonedHero - > set ( town - > garrisonHero ) ;
visitingHero - > set ( town - > visitingHero ) ;
}
void HeroSlots : : splitClicked ( )
{
if ( ! ! town - > visitingHero & & town - > garrisonHero & & ( visitingHero - > isSelected ( ) | | garrisonedHero - > isSelected ( ) ) )
{
2023-04-17 12:06:58 +02:00
LOCPLINT - > showHeroExchange ( town - > visitingHero - > id , town - > garrisonHero - > id ) ;
2018-04-07 13:34:11 +02:00
}
}
void HeroSlots : : swapArmies ( )
{
2023-04-02 23:43:18 +02:00
bool allow = true ;
//moving hero out of town - check if it is allowed
if ( town - > garrisonHero )
{
if ( ! town - > visitingHero & & LOCPLINT - > cb - > howManyHeroes ( false ) > = CGI - > settings ( ) - > getInteger ( EGameSettings : : HEROES_PER_PLAYER_ON_MAP_CAP ) )
{
std : : string text = CGI - > generaltexth - > translate ( " core.genrltxt.18 " ) ; //You already have %d adventuring heroes under your command.
boost : : algorithm : : replace_first ( text , " %d " , std : : to_string ( LOCPLINT - > cb - > howManyHeroes ( false ) ) ) ;
LOCPLINT - > showInfoDialog ( text , std : : vector < std : : shared_ptr < CComponent > > ( ) , soundBase : : sound_todo ) ;
allow = false ;
}
else if ( town - > garrisonHero - > stacksCount ( ) = = 0 )
{
//This hero has no creatures. A hero must have creatures before he can brave the dangers of the countryside.
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > translate ( " core.genrltxt.19 " ) , { } , soundBase : : sound_todo ) ;
allow = false ;
}
}
2018-04-07 13:34:11 +02:00
if ( ! town - > garrisonHero & & town - > visitingHero ) //visiting => garrison, merge armies: town army => hero army
{
if ( ! town - > visitingHero - > canBeMergedWith ( * town ) )
{
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 275 ] , std : : vector < std : : shared_ptr < CComponent > > ( ) , soundBase : : sound_todo ) ;
2023-04-02 23:43:18 +02:00
allow = false ;
2018-04-07 13:34:11 +02:00
}
}
2012-05-13 18:04:21 +03:00
2023-04-02 23:43:18 +02:00
garrisonedHero - > setHighlight ( false ) ;
visitingHero - > setHighlight ( false ) ;
if ( allow )
LOCPLINT - > cb - > swapGarrisonHero ( town ) ;
}
2018-04-07 13:34:11 +02:00
2008-01-15 23:38:01 +02:00
class SORTHELP
{
public :
2018-07-25 00:36:48 +02:00
bool operator ( ) ( const CIntObject * a , const CIntObject * b )
2008-01-15 23:38:01 +02:00
{
2018-07-25 00:36:48 +02:00
auto b1 = dynamic_cast < const CBuildingRect * > ( a ) ;
auto b2 = dynamic_cast < const CBuildingRect * > ( b ) ;
if ( ! b1 & & ! b2 )
return intptr_t ( a ) < intptr_t ( b ) ;
if ( b1 & & ! b2 )
return false ;
if ( ! b1 & & b2 )
return true ;
return ( * b1 ) < ( * b2 ) ;
2008-01-15 23:38:01 +02:00
}
2011-03-22 15:19:07 +02:00
} ;
2008-01-09 19:21:31 +02:00
2018-07-25 00:36:48 +02:00
SORTHELP buildSorter ;
2008-04-19 19:15:04 +03:00
2011-03-22 15:19:07 +02:00
CCastleBuildings : : CCastleBuildings ( const CGTownInstance * Town ) :
town ( Town ) ,
2013-06-26 14:18:27 +03:00
selectedBuilding ( nullptr )
2011-03-22 15:19:07 +02:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2008-04-19 19:15:04 +03:00
2018-04-07 13:34:11 +02:00
background = std : : make_shared < CPicture > ( town - > town - > clientInfo . townBackground ) ;
2023-02-20 18:37:33 +02:00
background - > needRefresh = true ;
background - > getSurface ( ) - > setBlitMode ( EImageBlitMode : : OPAQUE ) ;
2011-03-22 15:19:07 +02:00
pos . w = background - > pos . w ;
pos . h = background - > pos . h ;
2012-09-05 15:49:23 +03:00
recreate ( ) ;
}
2018-04-07 13:34:11 +02:00
CCastleBuildings : : ~ CCastleBuildings ( ) = default ;
2012-09-05 15:49:23 +03:00
void CCastleBuildings : : recreate ( )
{
selectedBuilding = nullptr ;
2018-07-25 00:36:48 +02:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2018-04-07 13:34:11 +02:00
2012-09-05 15:49:23 +03:00
buildings . clear ( ) ;
groups . clear ( ) ;
2011-03-22 15:19:07 +02:00
//Generate buildings list
2008-01-31 23:35:30 +02:00
2012-09-05 15:49:23 +03:00
auto buildingsCopy = town - > builtBuildings ; // a bit modified copy of built buildings
2009-07-20 11:18:33 +03:00
2013-02-11 02:24:57 +03:00
if ( vstd : : contains ( town - > builtBuildings , BuildingID : : SHIPYARD ) )
2011-03-22 15:19:07 +02:00
{
2015-12-08 06:33:13 +02:00
auto bayPos = town - > bestLocation ( ) ;
if ( ! bayPos . valid ( ) )
2017-08-10 18:39:27 +02:00
logGlobal - > warn ( " Shipyard in non-coastal town! " ) ;
2015-12-08 06:33:13 +02:00
std : : vector < const CGObjectInstance * > vobjs = LOCPLINT - > cb - > getVisitableObjs ( bayPos , false ) ;
2012-09-05 15:49:23 +03:00
//there is visitable obj at shipyard output tile and it's a boat or hero (on boat)
2012-09-23 21:01:04 +03:00
if ( ! vobjs . empty ( ) & & ( vobjs . front ( ) - > ID = = Obj : : BOAT | | vobjs . front ( ) - > ID = = Obj : : HERO ) )
2011-03-22 15:19:07 +02:00
{
2013-02-11 02:24:57 +03:00
buildingsCopy . insert ( BuildingID : : SHIP ) ;
2011-03-22 15:19:07 +02:00
}
}
2009-04-14 15:47:09 +03:00
2013-06-29 16:05:48 +03:00
for ( const CStructure * structure : town - > town - > clientInfo . structures )
2008-01-15 23:38:01 +02:00
{
2018-04-07 13:34:11 +02:00
if ( ! structure - > building )
2012-09-05 15:49:23 +03:00
{
2018-04-07 13:34:11 +02:00
buildings . push_back ( std : : make_shared < CBuildingRect > ( this , town , structure ) ) ;
2011-03-22 15:19:07 +02:00
continue ;
2012-09-05 15:49:23 +03:00
}
2018-04-07 13:34:11 +02:00
if ( vstd : : contains ( buildingsCopy , structure - > building - > bid ) )
2011-11-01 15:58:01 +03:00
{
2012-09-05 15:49:23 +03:00
groups [ structure - > building - > getBase ( ) ] . push_back ( structure ) ;
2011-11-01 15:58:01 +03:00
}
2012-09-05 15:49:23 +03:00
}
2013-12-02 14:58:02 +03:00
for ( auto & entry : groups )
{
const CBuilding * build = town - > town - > buildings . at ( entry . first ) ;
const CStructure * toAdd = * boost : : max_element ( entry . second , [ = ] ( const CStructure * a , const CStructure * b )
{
2021-02-20 03:57:50 +02:00
return build - > getDistance ( a - > building - > bid ) < build - > getDistance ( b - > building - > bid ) ;
2012-09-05 15:49:23 +03:00
} ) ;
2011-11-01 15:58:01 +03:00
2018-04-07 13:34:11 +02:00
buildings . push_back ( std : : make_shared < CBuildingRect > ( this , town , toAdd ) ) ;
2008-01-15 23:38:01 +02:00
}
2018-07-25 00:36:48 +02:00
boost : : sort ( children , buildSorter ) ; //TODO: create building in blit order
2011-03-22 15:19:07 +02:00
}
2013-12-02 14:58:02 +03:00
void CCastleBuildings : : addBuilding ( BuildingID building )
{
//FIXME: implement faster method without complete recreation of town
BuildingID base = town - > town - > buildings . at ( building ) - > getBase ( ) ;
recreate ( ) ;
auto & structures = groups . at ( base ) ;
2018-04-07 13:34:11 +02:00
for ( auto buildingRect : buildings )
2013-12-02 14:58:02 +03:00
{
2018-04-07 13:34:11 +02:00
if ( vstd : : contains ( structures , buildingRect - > str ) )
2011-03-22 15:19:07 +02:00
{
2012-09-05 15:49:23 +03:00
//reset animation
2018-04-07 13:34:11 +02:00
if ( structures . size ( ) = = 1 )
2023-01-15 20:56:55 +02:00
buildingRect - > stateTimeCounter = 0 ; // transparency -> fully visible stage
2012-09-05 15:49:23 +03:00
else
2023-01-16 01:33:53 +02:00
buildingRect - > stateTimeCounter = CBuildingRect : : BUILDING_APPEAR_TIMEPOINT ; // already in fully visible stage
2012-09-05 15:49:23 +03:00
break ;
2011-03-22 15:19:07 +02:00
}
2009-12-23 03:46:15 +02:00
}
2008-01-09 19:21:31 +02:00
}
2009-04-14 15:47:09 +03:00
2013-02-11 22:11:34 +03:00
void CCastleBuildings : : removeBuilding ( BuildingID building )
2008-01-09 19:21:31 +02:00
{
2012-09-05 15:49:23 +03:00
//FIXME: implement faster method without complete recreation of town
recreate ( ) ;
2011-03-22 15:19:07 +02:00
}
2018-04-07 13:34:11 +02:00
const CGHeroInstance * CCastleBuildings : : getHero ( )
2008-01-30 00:47:43 +02:00
{
2018-04-07 13:34:11 +02:00
if ( town - > visitingHero )
2011-03-22 15:19:07 +02:00
return town - > visitingHero ;
2018-04-07 13:34:11 +02:00
else
2011-03-22 15:19:07 +02:00
return town - > garrisonHero ;
2008-01-30 00:47:43 +02:00
}
2009-04-14 15:47:09 +03:00
2020-10-15 14:03:01 +02:00
void CCastleBuildings : : buildingClicked ( BuildingID building , BuildingSubID : : EBuildingSubID subID , BuildingID : : EBuildingID upgrades )
2008-03-10 01:06:35 +02:00
{
2017-08-11 13:38:10 +02:00
logGlobal - > trace ( " You've clicked on %d " , ( int ) building . toEnum ( ) ) ;
2012-09-02 13:33:41 +03:00
const CBuilding * b = town - > town - > buildings . find ( building ) - > second ;
2010-05-26 12:47:53 +03:00
2013-02-11 02:24:57 +03:00
if ( building > = BuildingID : : DWELL_FIRST )
2008-04-04 20:30:53 +03:00
{
2013-02-11 02:24:57 +03:00
enterDwelling ( ( building - BuildingID : : DWELL_FIRST ) % GameConstants : : CREATURES_PER_TOWN ) ;
2008-04-04 20:30:53 +03:00
}
2008-04-20 15:39:33 +03:00
else
2008-03-10 01:06:35 +02:00
{
2008-04-20 15:39:33 +03:00
switch ( building )
{
2013-02-11 02:24:57 +03:00
case BuildingID : : MAGES_GUILD_1 :
case BuildingID : : MAGES_GUILD_2 :
case BuildingID : : MAGES_GUILD_3 :
case BuildingID : : MAGES_GUILD_4 :
case BuildingID : : MAGES_GUILD_5 :
2011-03-22 15:19:07 +02:00
enterMagesGuild ( ) ;
2008-08-20 09:57:53 +03:00
break ;
2011-03-22 15:19:07 +02:00
2013-02-11 02:24:57 +03:00
case BuildingID : : TAVERN :
2011-03-22 15:19:07 +02:00
LOCPLINT - > showTavernWindow ( town ) ;
2008-10-26 22:58:34 +02:00
break ;
2011-03-22 15:19:07 +02:00
2013-02-11 02:24:57 +03:00
case BuildingID : : SHIPYARD :
2013-07-21 13:08:32 +03:00
if ( town - > shipyardStatus ( ) = = IBoatGenerator : : GOOD )
LOCPLINT - > showShipyardDialog ( town ) ;
2016-09-14 02:32:03 +02:00
else if ( town - > shipyardStatus ( ) = = IBoatGenerator : : BOAT_ALREADY_BUILT )
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 51 ] ) ;
2009-07-26 06:33:13 +03:00
break ;
2011-03-22 15:19:07 +02:00
2013-02-11 02:24:57 +03:00
case BuildingID : : FORT :
case BuildingID : : CITADEL :
case BuildingID : : CASTLE :
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CFortScreen > ( town ) ;
2008-08-17 12:11:16 +03:00
break ;
2011-03-22 15:19:07 +02:00
2013-02-11 02:24:57 +03:00
case BuildingID : : VILLAGE_HALL :
case BuildingID : : CITY_HALL :
case BuildingID : : TOWN_HALL :
case BuildingID : : CAPITOL :
2011-03-22 15:19:07 +02:00
enterTownHall ( ) ;
break ;
2013-02-11 02:24:57 +03:00
case BuildingID : : MARKETPLACE :
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CMarketplaceWindow > ( town , town - > visitingHero ) ;
2008-09-07 06:38:37 +03:00
break ;
2009-12-29 15:40:16 +02:00
2013-02-11 02:24:57 +03:00
case BuildingID : : BLACKSMITH :
2011-03-22 15:19:07 +02:00
enterBlacksmith ( town - > town - > warMachine ) ;
break ;
2020-10-02 23:55:46 +02:00
case BuildingID : : SHIP :
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 51 ] ) ; //Cannot build another boat
break ;
2013-02-11 02:24:57 +03:00
case BuildingID : : SPECIAL_1 :
2020-10-02 23:55:46 +02:00
case BuildingID : : SPECIAL_2 :
case BuildingID : : SPECIAL_3 :
switch ( subID )
2008-08-27 13:19:18 +03:00
{
2020-10-02 23:55:46 +02:00
case BuildingSubID : : NONE :
2023-03-28 16:36:46 +02:00
enterBuilding ( building ) ;
2020-10-02 23:55:46 +02:00
break ;
case BuildingSubID : : MYSTIC_POND :
2020-10-15 14:03:01 +02:00
enterFountain ( building , subID , upgrades ) ;
2011-03-22 15:19:07 +02:00
break ;
2020-10-02 23:55:46 +02:00
case BuildingSubID : : ARTIFACT_MERCHANT :
2011-03-22 15:19:07 +02:00
if ( town - > visitingHero )
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CMarketplaceWindow > ( town , town - > visitingHero , EMarketMode : : RESOURCE_ARTIFACT ) ;
2011-03-22 15:19:07 +02:00
else
2023-01-04 15:17:50 +02:00
LOCPLINT - > showInfoDialog ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 273 ] ) % b - > getNameTranslated ( ) ) ) ; //Only visiting heroes may use the %s.
2011-03-22 15:19:07 +02:00
break ;
2010-10-31 21:17:26 +02:00
2020-10-02 23:55:46 +02:00
case BuildingSubID : : FOUNTAIN_OF_FORTUNE :
2020-10-15 14:03:01 +02:00
enterFountain ( building , subID , upgrades ) ;
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
break ;
2011-03-22 15:19:07 +02:00
2020-10-02 23:55:46 +02:00
case BuildingSubID : : FREELANCERS_GUILD :
2011-03-22 15:19:07 +02:00
if ( getHero ( ) )
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CMarketplaceWindow > ( town , getHero ( ) , EMarketMode : : CREATURE_RESOURCE ) ;
2011-03-22 15:19:07 +02:00
else
2023-01-04 15:17:50 +02:00
LOCPLINT - > showInfoDialog ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 273 ] ) % b - > getNameTranslated ( ) ) ) ; //Only visiting heroes may use the %s.
2011-03-22 15:19:07 +02:00
break ;
2020-10-02 23:55:46 +02:00
case BuildingSubID : : MAGIC_UNIVERSITY :
2011-03-22 15:19:07 +02:00
if ( getHero ( ) )
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CUniversityWindow > ( getHero ( ) , town ) ;
2011-03-22 15:19:07 +02:00
else
enterBuilding ( building ) ;
break ;
2010-11-15 17:15:00 +02:00
2020-10-02 23:55:46 +02:00
case BuildingSubID : : BROTHERHOOD_OF_SWORD :
2020-10-15 14:03:01 +02:00
if ( upgrades = = BuildingID : : TAVERN )
LOCPLINT - > showTavernWindow ( town ) ;
else
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
enterBuilding ( building ) ;
2011-03-22 15:19:07 +02:00
break ;
2020-10-02 23:55:46 +02:00
case BuildingSubID : : CASTLE_GATE :
2011-03-22 15:19:07 +02:00
enterCastleGate ( ) ;
break ;
2010-11-15 17:15:00 +02:00
2020-10-02 23:55:46 +02:00
case BuildingSubID : : CREATURE_TRANSFORMER : //Skeleton Transformer
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CTransformerWindow > ( town , getHero ( ) ) ;
2010-07-03 15:00:53 +03:00
break ;
2010-11-15 17:15:00 +02:00
2020-10-02 23:55:46 +02:00
case BuildingSubID : : PORTAL_OF_SUMMONING :
2011-12-14 00:23:17 +03:00
if ( town - > creatures [ GameConstants : : CREATURES_PER_TOWN ] . second . empty ( ) ) //No creatures
2011-03-22 15:19:07 +02:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > tcommands [ 30 ] ) ;
2010-11-15 17:15:00 +02:00
else
2011-12-14 00:23:17 +03:00
enterDwelling ( GameConstants : : CREATURES_PER_TOWN ) ;
2011-03-22 15:19:07 +02:00
break ;
2020-10-02 23:55:46 +02:00
case BuildingSubID : : BALLISTA_YARD :
2013-02-07 20:34:50 +03:00
enterBlacksmith ( ArtifactID : : BALLISTA ) ;
2011-03-22 15:19:07 +02:00
break ;
2009-05-22 02:50:45 +03:00
default :
2011-03-22 15:19:07 +02:00
enterBuilding ( building ) ;
break ;
2009-05-22 02:50:45 +03:00
}
break ;
2011-03-22 15:19:07 +02:00
2009-12-30 09:49:25 +02:00
default :
2011-03-22 15:19:07 +02:00
enterBuilding ( building ) ;
2009-12-29 15:40:16 +02:00
break ;
2008-04-20 15:39:33 +03:00
}
2008-03-10 01:06:35 +02:00
}
2009-12-30 09:49:25 +02:00
}
2010-06-26 13:01:26 +03:00
2013-02-11 02:24:57 +03:00
void CCastleBuildings : : enterBlacksmith ( ArtifactID artifactID )
2010-06-26 13:01:26 +03:00
{
2011-03-22 15:19:07 +02:00
const CGHeroInstance * hero = town - > visitingHero ;
if ( ! hero )
{
2023-01-04 15:17:50 +02:00
LOCPLINT - > showInfoDialog ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 273 ] ) % town - > town - > buildings . find ( BuildingID : : BLACKSMITH ) - > second - > getNameTranslated ( ) ) ) ;
2011-03-22 15:19:07 +02:00
return ;
}
2023-03-13 12:28:33 +02:00
auto art = artifactID . toArtifact ( ) ;
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
int price = art - > getPrice ( ) ;
2023-04-05 02:26:29 +02:00
bool possible = LOCPLINT - > cb - > getResourceAmount ( EGameResID : : GOLD ) > = price ;
2023-03-05 16:40:20 +02:00
if ( possible )
{
2023-07-03 22:11:56 +02:00
for ( auto slot : art - > getPossibleSlots ( ) . at ( ArtBearer : : HERO ) )
2023-03-05 16:40:20 +02:00
{
if ( hero - > getArt ( slot ) = = nullptr )
{
possible = true ;
break ;
}
else
{
possible = false ;
}
}
}
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
CreatureID cre = art - > getWarMachine ( ) ;
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CBlacksmithDialog > ( possible , cre , artifactID , hero - > id ) ;
2010-06-26 13:01:26 +03:00
}
2013-02-11 22:11:34 +03:00
void CCastleBuildings : : enterBuilding ( BuildingID building )
2009-12-30 09:49:25 +02:00
{
2018-04-07 13:34:11 +02:00
std : : vector < std : : shared_ptr < CComponent > > comps ( 1 , std : : make_shared < CComponent > ( CComponent : : building , town - > subID , building ) ) ;
2023-01-04 15:17:50 +02:00
LOCPLINT - > showInfoDialog ( town - > town - > buildings . find ( building ) - > second - > getDescriptionTranslated ( ) , comps ) ;
2011-03-22 15:19:07 +02:00
}
void CCastleBuildings : : enterCastleGate ( )
{
if ( ! town - > visitingHero )
{
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 126 ] ) ;
return ; //only visiting hero can use castle gates
}
std : : vector < int > availableTowns ;
2015-10-15 04:28:28 +02:00
std : : vector < const CGTownInstance * > Towns = LOCPLINT - > cb - > getTownsInfo ( true ) ;
2013-06-29 16:05:48 +03:00
for ( auto & Town : Towns )
2011-03-22 15:19:07 +02:00
{
2013-06-29 16:05:48 +03:00
const CGTownInstance * t = Town ;
2013-06-26 14:18:27 +03:00
if ( t - > id ! = this - > town - > id & & t - > visitingHero = = nullptr & & //another town, empty and this is
2023-01-04 15:17:50 +02:00
t - > town - > faction - > getId ( ) = = town - > town - > faction - > getId ( ) & & //the town of the same faction
2020-10-02 23:55:46 +02:00
t - > hasBuilt ( BuildingSubID : : CASTLE_GATE ) ) //and the town has a castle gate
2011-03-22 15:19:07 +02:00
{
2013-02-14 02:55:42 +03:00
availableTowns . push_back ( t - > id . getNum ( ) ) ; //add to the list
2011-03-22 15:19:07 +02:00
}
}
2018-04-07 13:34:11 +02:00
auto gateIcon = std : : make_shared < CAnimImage > ( town - > town - > clientInfo . buildingsIcons , BuildingID : : CASTLE_GATE ) ; //will be deleted by selection window
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CObjectListWindow > ( availableTowns , gateIcon , CGI - > generaltexth - > jktexts [ 40 ] ,
2018-07-25 00:36:48 +02:00
CGI - > generaltexth - > jktexts [ 41 ] , std : : bind ( & CCastleInterface : : castleTeleport , LOCPLINT - > castleInt , _1 ) ) ;
2011-03-22 15:19:07 +02:00
}
void CCastleBuildings : : enterDwelling ( int level )
{
2023-08-06 11:46:29 +02:00
if ( level < 0 | | level > = town - > creatures . size ( ) | | town - > creatures [ level ] . second . empty ( ) )
{
assert ( 0 ) ;
logGlobal - > error ( " Attempt to enter into invalid dwelling of level %d in town %s (%s) " , level , town - > getNameTranslated ( ) , town - > town - > faction - > getNameTranslated ( ) ) ;
return ;
}
2023-02-02 21:54:47 +02:00
auto recruitCb = [ = ] ( CreatureID id , int count )
{
LOCPLINT - > cb - > recruitCreatures ( town , town - > getUpperArmy ( ) , id , count , level ) ;
} ;
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CRecruitmentWindow > ( town , level , town , recruitCb , - 87 ) ;
2008-03-10 01:06:35 +02:00
}
2009-04-14 15:47:09 +03:00
2017-11-01 15:58:49 +02:00
void CCastleBuildings : : enterToTheQuickRecruitmentWindow ( )
{
2022-09-18 11:38:50 +02:00
const auto beginIt = town - > creatures . cbegin ( ) ;
const auto afterLastIt = town - > creatures . size ( ) > GameConstants : : CREATURES_PER_TOWN
? std : : next ( beginIt , GameConstants : : CREATURES_PER_TOWN )
: town - > creatures . cend ( ) ;
const auto hasSomeoneToRecruit = std : : any_of ( beginIt , afterLastIt ,
2022-09-17 14:41:56 +02:00
[ ] ( const auto & creatureInfo ) { return creatureInfo . first > 0 ; } ) ;
if ( hasSomeoneToRecruit )
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < QuickRecruitmentWindow > ( town , pos ) ;
2022-09-17 14:41:56 +02:00
else
2022-12-27 22:19:05 +02:00
CInfoWindow : : showInfoDialog ( CGI - > generaltexth - > translate ( " vcmi.townHall.noCreaturesToRecruit " ) , { } ) ;
2017-11-01 15:58:49 +02:00
}
2020-10-15 14:03:01 +02:00
void CCastleBuildings : : enterFountain ( const BuildingID & building , BuildingSubID : : EBuildingSubID subID , BuildingID : : EBuildingID upgrades )
2010-01-25 23:25:14 +02:00
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
std : : vector < std : : shared_ptr < CComponent > > comps ( 1 , std : : make_shared < CComponent > ( CComponent : : building , town - > subID , building ) ) ;
2023-01-04 15:17:50 +02:00
std : : string descr = town - > town - > buildings . find ( building ) - > second - > getDescriptionTranslated ( ) ;
2020-10-25 00:04:34 +02:00
std : : string hasNotProduced ;
std : : string hasProduced ;
2023-04-09 17:26:32 +02:00
if ( this - > town - > town - > faction - > getIndex ( ) = = ETownType : : RAMPART )
2020-10-25 00:04:34 +02:00
{
hasNotProduced = CGI - > generaltexth - > allTexts [ 677 ] ;
hasProduced = CGI - > generaltexth - > allTexts [ 678 ] ;
}
else
{
2023-01-04 15:17:50 +02:00
auto buildingName = town - > town - > getSpecialBuilding ( subID ) - > getNameTranslated ( ) ;
2020-10-25 00:04:34 +02:00
2022-12-27 22:19:05 +02:00
hasNotProduced = std : : string ( CGI - > generaltexth - > translate ( " vcmi.townHall.hasNotProduced " ) ) ;
hasProduced = std : : string ( CGI - > generaltexth - > translate ( " vcmi.townHall.hasProduced " ) ) ;
2020-10-25 00:04:34 +02:00
boost : : algorithm : : replace_first ( hasNotProduced , " %s " , buildingName ) ;
boost : : algorithm : : replace_first ( hasProduced , " %s " , buildingName ) ;
}
2012-09-05 15:49:23 +03:00
2021-02-20 03:57:50 +02:00
bool isMysticPondOrItsUpgrade = subID = = BuildingSubID : : MYSTIC_POND
| | ( upgrades ! = BuildingID : : NONE
2020-10-15 14:03:01 +02:00
& & town - > town - > buildings . find ( BuildingID ( upgrades ) ) - > second - > subId = = BuildingSubID : : MYSTIC_POND ) ;
2012-09-05 15:49:23 +03:00
2020-10-15 14:03:01 +02:00
if ( upgrades ! = BuildingID : : NONE )
2023-01-04 15:17:50 +02:00
descr + = " \n \n " + town - > town - > buildings . find ( BuildingID ( upgrades ) ) - > second - > getDescriptionTranslated ( ) ;
2020-10-15 14:03:01 +02:00
if ( isMysticPondOrItsUpgrade ) //for vanila Rampart like towns
2010-01-25 23:25:14 +02:00
{
2020-10-15 14:03:01 +02:00
if ( town - > bonusValue . first = = 0 ) //Mystic Pond produced nothing;
2020-10-25 00:04:34 +02:00
descr + = " \n \n " + hasNotProduced ;
2020-10-15 14:03:01 +02:00
else //Mystic Pond produced something;
{
2020-10-25 00:04:34 +02:00
descr + = " \n \n " + hasProduced ;
2021-02-20 03:57:50 +02:00
boost : : algorithm : : replace_first ( descr , " %s " , CGI - > generaltexth - > restypes [ town - > bonusValue . first ] ) ;
2023-03-09 15:36:46 +02:00
boost : : algorithm : : replace_first ( descr , " %d " , std : : to_string ( town - > bonusValue . second ) ) ;
2021-02-20 03:57:50 +02:00
}
2010-01-28 18:15:46 +02:00
}
2011-03-22 15:19:07 +02:00
LOCPLINT - > showInfoDialog ( descr , comps ) ;
2010-01-25 23:25:14 +02:00
}
2011-03-22 15:19:07 +02:00
void CCastleBuildings : : enterMagesGuild ( )
2010-01-25 23:25:14 +02:00
{
2011-03-22 15:19:07 +02:00
const CGHeroInstance * hero = getHero ( ) ;
if ( hero & & ! hero - > hasSpellbook ( ) ) //hero doesn't have spellbok
2010-01-25 23:25:14 +02:00
{
2018-08-11 17:25:09 +02:00
const StartInfo * si = LOCPLINT - > cb - > getStartInfo ( ) ;
// it would be nice to find a way to move this hack to config/mapOverrides.json
2023-06-25 20:16:03 +02:00
if ( si & & si - > campState & & si - > campState & & // We're in campaign,
2023-06-26 00:07:55 +02:00
( si - > campState - > getFilename ( ) = = " DATA/YOG.H3C " ) & & // which is "Birth of a Barbarian",
2018-08-11 17:25:09 +02:00
( hero - > subID = = 45 ) ) // and the hero is Yog (based on Solmyr)
{
// "Yog has given up magic in all its forms..."
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 736 ] ) ;
}
2023-04-05 02:26:29 +02:00
else if ( LOCPLINT - > cb - > getResourceAmount ( EGameResID : : GOLD ) < 500 ) //not enough gold to buy spellbook
2011-03-22 15:19:07 +02:00
{
2012-06-02 18:16:54 +03:00
openMagesGuild ( ) ;
2011-03-22 15:19:07 +02:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 213 ] ) ;
}
else
{
2017-07-19 01:06:05 +02:00
CFunctionList < void ( ) > onYes = [ this ] ( ) { openMagesGuild ( ) ; } ;
2012-06-02 18:16:54 +03:00
CFunctionList < void ( ) > onNo = onYes ;
2017-07-19 01:06:05 +02:00
onYes + = [ hero ] ( ) { LOCPLINT - > cb - > buyArtifact ( hero , ArtifactID : : SPELLBOOK ) ; } ;
2018-04-07 13:34:11 +02:00
std : : vector < std : : shared_ptr < CComponent > > components ( 1 , std : : make_shared < CComponent > ( CComponent : : artifact , ArtifactID : : SPELLBOOK , 0 ) ) ;
2011-03-22 15:19:07 +02:00
2018-04-07 13:34:11 +02:00
LOCPLINT - > showYesNoDialog ( CGI - > generaltexth - > allTexts [ 214 ] , onYes , onNo , components ) ;
2011-03-22 15:19:07 +02:00
}
2010-01-25 23:25:14 +02:00
}
2011-03-22 15:19:07 +02:00
else
{
openMagesGuild ( ) ;
}
}
void CCastleBuildings : : enterTownHall ( )
{
2022-11-29 00:11:46 +02:00
if ( town - > visitingHero & & town - > visitingHero - > hasArt ( ArtifactID : : GRAIL ) & &
2013-02-11 02:24:57 +03:00
! vstd : : contains ( town - > builtBuildings , BuildingID : : GRAIL ) ) //hero has grail, but town does not have it
2011-03-22 15:19:07 +02:00
{
2013-02-11 02:24:57 +03:00
if ( ! vstd : : contains ( town - > forbiddenBuildings , BuildingID : : GRAIL ) )
2011-03-22 15:19:07 +02:00
{
LOCPLINT - > showYesNoDialog ( CGI - > generaltexth - > allTexts [ 597 ] , //Do you wish this to be the permanent home of the Grail?
2017-07-19 00:39:38 +02:00
[ & ] ( ) { LOCPLINT - > cb - > buildBuilding ( town , BuildingID : : GRAIL ) ; } ,
2018-04-07 13:34:11 +02:00
[ & ] ( ) { openTownHall ( ) ; } ) ;
2011-03-22 15:19:07 +02:00
}
else
{
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > allTexts [ 673 ] ) ;
2023-05-16 17:34:23 +02:00
assert ( GH . windows ( ) . topWindow < CInfoWindow > ( ) ! = nullptr ) ;
GH . windows ( ) . topWindow < CInfoWindow > ( ) - > buttons [ 0 ] - > addCallback ( std : : bind ( & CCastleBuildings : : openTownHall , this ) ) ;
2011-03-22 15:19:07 +02:00
}
}
else
{
openTownHall ( ) ;
}
}
void CCastleBuildings : : openMagesGuild ( )
{
2014-04-24 22:36:10 +03:00
std : : string mageGuildBackground ;
mageGuildBackground = LOCPLINT - > castleInt - > town - > town - > clientInfo . guildBackground ;
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CMageGuildScreen > ( LOCPLINT - > castleInt , mageGuildBackground ) ;
2010-01-25 23:25:14 +02:00
}
2011-03-22 15:19:07 +02:00
void CCastleBuildings : : openTownHall ( )
2008-03-10 01:06:35 +02:00
{
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CHallInterface > ( town ) ;
2011-03-22 15:19:07 +02:00
}
2023-02-02 21:54:47 +02:00
CCreaInfo : : CCreaInfo ( Point position , const CGTownInstance * Town , int Level , bool compact , bool _showAvailable ) :
2011-04-07 20:54:08 +03:00
town ( Town ) ,
2011-07-18 18:21:16 +03:00
level ( Level ) ,
2023-02-02 21:54:47 +02:00
showAvailable ( _showAvailable )
2009-12-23 03:46:15 +02:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2011-07-18 18:21:16 +03:00
pos + = position ;
2014-03-07 16:21:09 +03:00
2018-04-07 13:34:11 +02:00
if ( town - > creatures . size ( ) < = level | | town - > creatures [ level ] . second . empty ( ) )
2011-04-07 20:54:08 +03:00
{
level = - 1 ;
return ; //No creature
}
2023-06-13 18:33:35 +02:00
addUsedEvents ( LCLICK | SHOW_POPUP | HOVER ) ;
2011-04-07 20:54:08 +03:00
2011-12-14 00:23:17 +03:00
ui32 creatureID = town - > creatures [ level ] . second . back ( ) ;
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
creature = CGI - > creh - > objects [ creatureID ] ;
2011-04-07 20:54:08 +03:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
picture = std : : make_shared < CAnimImage > ( " CPRSMALL " , creature - > getIconIndex ( ) , 0 , 8 , 0 ) ;
2011-07-18 18:21:16 +03:00
std : : string value ;
2018-04-07 13:34:11 +02:00
if ( showAvailable )
2023-03-09 15:36:46 +02:00
value = std : : to_string ( town - > creatures [ level ] . first ) ;
2011-07-18 18:21:16 +03:00
else
2023-03-09 15:36:46 +02:00
value = std : : string ( " + " ) + std : : to_string ( town - > creatureGrowth ( level ) ) ;
2011-07-18 18:21:16 +03:00
2018-04-07 13:34:11 +02:00
if ( compact )
2011-07-18 18:21:16 +03:00
{
2022-11-26 23:12:20 +02:00
label = std : : make_shared < CLabel > ( 40 , 32 , FONT_TINY , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE , value ) ;
2011-07-18 18:21:16 +03:00
pos . x + = 8 ;
pos . w = 32 ;
pos . h = 32 ;
}
else
{
2022-11-26 23:12:20 +02:00
label = std : : make_shared < CLabel > ( 24 , 40 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , value ) ;
2011-07-18 18:21:16 +03:00
pos . w = 48 ;
pos . h = 48 ;
}
}
void CCreaInfo : : update ( )
{
2018-04-07 13:34:11 +02:00
if ( label )
2011-07-18 18:21:16 +03:00
{
std : : string value ;
2018-04-07 13:34:11 +02:00
if ( showAvailable )
2023-03-09 15:36:46 +02:00
value = std : : to_string ( town - > creatures [ level ] . first ) ;
2011-07-18 18:21:16 +03:00
else
2023-03-09 15:36:46 +02:00
value = std : : string ( " + " ) + std : : to_string ( town - > creatureGrowth ( level ) ) ;
2011-07-18 18:21:16 +03:00
2022-12-19 22:04:50 +02:00
if ( value ! = label - > getText ( ) )
2013-08-29 16:46:27 +03:00
label - > setText ( value ) ;
2011-07-18 18:21:16 +03:00
}
2009-12-23 03:46:15 +02:00
}
2011-04-07 20:54:08 +03:00
void CCreaInfo : : hover ( bool on )
2009-12-23 03:46:15 +02:00
{
2011-04-30 21:16:58 +03:00
std : : string message = CGI - > generaltexth - > allTexts [ 588 ] ;
2023-01-02 18:00:51 +02:00
boost : : algorithm : : replace_first ( message , " %s " , creature - > getNamePluralTranslated ( ) ) ;
2011-04-30 21:16:58 +03:00
2009-12-23 03:46:15 +02:00
if ( on )
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( message ) ;
2009-12-23 03:46:15 +02:00
}
2022-11-18 17:54:10 +02:00
else
2018-04-07 13:34:11 +02:00
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clearIfMatching ( message ) ;
2018-04-07 13:34:11 +02:00
}
2009-12-23 03:46:15 +02:00
}
2010-07-10 19:50:23 +03:00
2023-07-09 16:48:25 +02:00
void CCreaInfo : : clickPressed ( const Point & cursorPosition )
2011-07-18 18:21:16 +03:00
{
2023-07-08 13:33:04 +02:00
int offset = LOCPLINT - > castleInt ? ( - 87 ) : 0 ;
auto recruitCb = [ = ] ( CreatureID id , int count )
2011-07-18 18:21:16 +03:00
{
2023-07-08 13:33:04 +02:00
LOCPLINT - > cb - > recruitCreatures ( town , town - > getUpperArmy ( ) , id , count , level ) ;
} ;
GH . windows ( ) . createAndPushWindow < CRecruitmentWindow > ( town , level , town , recruitCb , offset ) ;
2010-07-10 19:50:23 +03:00
}
2009-12-23 03:46:15 +02:00
2011-07-18 18:21:16 +03:00
std : : string CCreaInfo : : genGrowthText ( )
2009-12-23 03:46:15 +02:00
{
2011-08-26 23:32:05 +03:00
GrowthInfo gi = town - > getGrowthInfo ( level ) ;
2023-01-02 18:00:51 +02:00
std : : string descr = boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 589 ] ) % creature - > getNameSingularTranslated ( ) % gi . totalGrowth ( ) ) ;
2009-12-23 03:46:15 +02:00
2018-04-07 13:34:11 +02:00
for ( const GrowthInfo : : Entry & entry : gi . entries )
2011-08-26 23:32:05 +03:00
descr + = " \n " + entry . description ;
2014-03-07 16:21:09 +03:00
2011-07-18 18:21:16 +03:00
return descr ;
}
2009-12-23 03:46:15 +02:00
2023-07-08 13:33:04 +02:00
void CCreaInfo : : showPopupWindow ( const Point & cursorPosition )
2011-07-18 18:21:16 +03:00
{
2023-06-11 17:20:10 +02:00
if ( showAvailable )
GH . windows ( ) . createAndPushWindow < CDwellingInfoBox > ( GH . screenDimensions ( ) . x / 2 , GH . screenDimensions ( ) . y / 2 , town , level ) ;
else
CRClickPopup : : createAndPush ( genGrowthText ( ) , std : : make_shared < CComponent > ( CComponent : : creature , creature - > getId ( ) ) ) ;
2009-12-23 03:46:15 +02:00
}
2010-06-30 22:27:35 +03:00
2023-02-02 21:54:47 +02:00
bool CCreaInfo : : getShowAvailable ( )
{
return showAvailable ;
}
2018-04-07 13:34:11 +02:00
CTownInfo : : CTownInfo ( int posX , int posY , const CGTownInstance * Town , bool townHall )
: town ( Town ) ,
2013-06-26 14:18:27 +03:00
building ( nullptr )
2009-12-23 03:46:15 +02:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2023-06-13 18:33:35 +02:00
addUsedEvents ( SHOW_POPUP | HOVER ) ;
2011-04-07 20:54:08 +03:00
pos . x + = posX ;
pos . y + = posY ;
int buildID ;
2010-06-30 22:27:35 +03:00
2018-04-07 13:34:11 +02:00
if ( townHall )
2011-04-07 20:54:08 +03:00
{
buildID = 10 + town - > hallLevel ( ) ;
2018-04-07 13:34:11 +02:00
picture = std : : make_shared < CAnimImage > ( " ITMTL.DEF " , town - > hallLevel ( ) ) ;
2011-04-07 20:54:08 +03:00
}
else
2009-12-23 03:46:15 +02:00
{
2011-04-07 20:54:08 +03:00
buildID = 6 + town - > fortLevel ( ) ;
2018-04-07 13:34:11 +02:00
if ( buildID = = 6 )
2016-11-27 18:00:16 +02:00
return ; //FIXME: suspicious statement, fix or comment
2018-04-07 13:34:11 +02:00
picture = std : : make_shared < CAnimImage > ( " ITMCL.DEF " , town - > fortLevel ( ) - 1 ) ;
2013-12-02 14:58:02 +03:00
}
building = town - > town - > buildings . at ( BuildingID ( buildID ) ) ;
pos = picture - > pos ;
}
2011-04-07 20:54:08 +03:00
void CTownInfo : : hover ( bool on )
2009-12-23 03:46:15 +02:00
{
if ( on )
{
2018-04-07 13:34:11 +02:00
if ( building )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( building - > getNameTranslated ( ) ) ;
2009-12-23 03:46:15 +02:00
}
else
2018-04-07 13:34:11 +02:00
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2018-04-07 13:34:11 +02:00
}
2009-12-23 03:46:15 +02:00
}
2010-06-30 22:27:35 +03:00
2023-07-08 13:33:04 +02:00
void CTownInfo : : showPopupWindow ( const Point & cursorPosition )
2012-12-11 15:12:46 +03:00
{
2023-06-11 17:20:10 +02:00
if ( building )
2018-04-07 13:34:11 +02:00
{
2023-01-04 15:17:50 +02:00
auto c = std : : make_shared < CComponent > ( CComponent : : building , building - > town - > faction - > getIndex ( ) , building - > bid ) ;
CRClickPopup : : createAndPush ( CInfoWindow : : genText ( building - > getNameTranslated ( ) , building - > getDescriptionTranslated ( ) ) , c ) ;
2018-04-07 13:34:11 +02:00
}
2009-12-23 03:46:15 +02:00
}
2010-06-30 22:27:35 +03:00
2018-04-07 13:34:11 +02:00
CCastleInterface : : CCastleInterface ( const CGTownInstance * Town , const CGTownInstance * from ) :
2018-10-29 15:12:07 +02:00
CStatusbarWindow ( PLAYER_COLORED | BORDERED ) ,
2018-04-07 13:34:11 +02:00
town ( Town )
2009-07-20 11:18:33 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2009-07-20 11:18:33 +03:00
2018-04-07 13:34:11 +02:00
LOCPLINT - > castleInt = this ;
addUsedEvents ( KEYBOARD ) ;
2012-10-07 17:58:48 +03:00
2018-04-07 13:34:11 +02:00
builds = std : : make_shared < CCastleBuildings > ( town ) ;
panel = std : : make_shared < CPicture > ( " TOWNSCRN " , 0 , builds - > pos . h ) ;
panel - > colorize ( LOCPLINT - > playerID ) ;
pos . w = panel - > pos . w ;
pos . h = builds - > pos . h + panel - > pos . h ;
center ( ) ;
updateShadow ( ) ;
2012-10-07 17:58:48 +03:00
2023-07-07 00:08:29 +02:00
garr = std : : make_shared < CGarrisonInt > ( Point ( 305 , 387 ) , 4 , Point ( 0 , 96 ) , town - > getUpperArmy ( ) , town - > visitingHero ) ;
2023-07-03 18:24:12 +02:00
garr - > setRedrawParent ( true ) ;
2012-10-07 17:58:48 +03:00
2018-04-07 13:34:11 +02:00
heroes = std : : make_shared < HeroSlots > ( town , Point ( 241 , 387 ) , Point ( 241 , 483 ) , garr , true ) ;
2023-01-04 15:17:50 +02:00
title = std : : make_shared < CLabel > ( 85 , 387 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , town - > getNameTranslated ( ) ) ;
2022-11-26 23:12:20 +02:00
income = std : : make_shared < CLabel > ( 195 , 443 , FONT_SMALL , ETextAlignment : : CENTER ) ;
2018-04-07 13:34:11 +02:00
icon = std : : make_shared < CAnimImage > ( " ITPT " , 0 , 0 , 15 , 387 ) ;
2023-04-27 19:21:06 +02:00
exit = std : : make_shared < CButton > ( Point ( 744 , 544 ) , " TSBTNS " , CButton : : tooltip ( CGI - > generaltexth - > tcommands [ 8 ] ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_RETURN ) ;
2018-04-07 13:34:11 +02:00
exit - > setImageOrder ( 4 , 5 , 6 , 7 ) ;
2018-11-14 19:58:37 +02:00
auto split = std : : make_shared < CButton > ( Point ( 744 , 382 ) , " TSBTNS " , CButton : : tooltip ( CGI - > generaltexth - > tcommands [ 3 ] ) , [ & ] ( )
{
garr - > splitClick ( ) ;
heroes - > splitClicked ( ) ;
} ) ;
2018-04-07 13:34:11 +02:00
garr - > addSplitBtn ( split ) ;
Rect barRect ( 9 , 182 , 732 , 18 ) ;
2023-01-30 13:58:13 +02:00
auto statusbarBackground = std : : make_shared < CPicture > ( panel - > getSurface ( ) , barRect , 9 , 555 ) ;
2018-08-26 18:09:56 +02:00
statusbar = CGStatusBar : : create ( statusbarBackground ) ;
2023-05-07 23:31:34 +02:00
resdatabar = std : : make_shared < CResDataBar > ( " ARESBAR " , 3 , 575 , 37 , 3 , 84 , 78 ) ;
2018-04-07 13:34:11 +02:00
2023-05-07 23:31:34 +02:00
townlist = std : : make_shared < CTownList > ( 3 , Rect ( Point ( 743 , 414 ) , Point ( 48 , 128 ) ) , Point ( 1 , 16 ) , Point ( 0 , 32 ) , LOCPLINT - > localState - > getOwnedTowns ( ) . size ( ) ) ;
2023-04-26 14:44:10 +02:00
townlist - > setScrollUpButton ( std : : make_shared < CButton > ( Point ( 744 , 414 ) , " IAM014 " , CButton : : tooltipLocalized ( " core.help.306 " ) ) ) ;
townlist - > setScrollDownButton ( std : : make_shared < CButton > ( Point ( 744 , 526 ) , " IAM015 " , CButton : : tooltipLocalized ( " core.help.307 " ) ) ) ;
2018-04-07 13:34:11 +02:00
if ( from )
townlist - > select ( from ) ;
townlist - > select ( town ) ; //this will scroll list to select current town
townlist - > onSelect = std : : bind ( & CCastleInterface : : townChange , this ) ;
recreateIcons ( ) ;
2023-04-28 15:53:45 +02:00
if ( ! from )
adventureInt - > onAudioPaused ( ) ;
2022-11-13 14:24:15 +02:00
CCS - > musich - > playMusic ( town - > town - > clientInfo . musicTheme , true , false ) ;
2009-07-20 11:18:33 +03:00
}
2018-04-07 13:34:11 +02:00
CCastleInterface : : ~ CCastleInterface ( )
2011-04-30 21:16:58 +03:00
{
2023-04-28 15:53:45 +02:00
// resume map audio if:
// adventureInt exists (may happen on exiting client with open castle interface)
// castleInt has not been replaced (happens on switching between towns inside castle interface)
if ( adventureInt & & LOCPLINT - > castleInt = = this )
2023-03-25 23:30:46 +02:00
adventureInt - > onAudioResumed ( ) ;
2018-07-25 00:36:48 +02:00
if ( LOCPLINT - > castleInt = = this )
LOCPLINT - > castleInt = nullptr ;
2011-04-30 21:16:58 +03:00
}
2018-04-07 13:34:11 +02:00
void CCastleInterface : : updateGarrisons ( )
2011-04-30 21:16:58 +03:00
{
2018-04-07 13:34:11 +02:00
garr - > recreateSlots ( ) ;
2011-04-30 21:16:58 +03:00
}
2018-04-07 13:34:11 +02:00
void CCastleInterface : : close ( )
2009-09-09 09:04:42 +03:00
{
2018-04-07 13:34:11 +02:00
if ( town - > tempOwner = = LOCPLINT - > playerID ) //we may have opened window for an allied town
2009-09-09 09:04:42 +03:00
{
2018-04-07 13:34:11 +02:00
if ( town - > visitingHero & & town - > visitingHero - > tempOwner = = LOCPLINT - > playerID )
2023-04-18 22:08:27 +02:00
LOCPLINT - > localState - > setSelection ( town - > visitingHero ) ;
2018-04-07 13:34:11 +02:00
else
2023-04-18 22:08:27 +02:00
LOCPLINT - > localState - > setSelection ( town ) ;
2009-09-09 09:04:42 +03:00
}
2018-04-07 13:34:11 +02:00
CWindowObject : : close ( ) ;
2009-09-09 09:04:42 +03:00
}
2018-04-07 13:34:11 +02:00
void CCastleInterface : : castleTeleport ( int where )
2012-07-21 23:16:54 +03:00
{
2018-04-07 13:34:11 +02:00
const CGTownInstance * dest = LOCPLINT - > cb - > getTown ( ObjectInstanceID ( where ) ) ;
2023-04-17 12:06:58 +02:00
LOCPLINT - > localState - > setSelection ( town - > visitingHero ) ; //according to assert(ho == adventureInt->selection) in the eraseCurrentPathOf
2018-04-07 13:34:11 +02:00
LOCPLINT - > cb - > teleportHero ( town - > visitingHero , dest ) ;
2023-04-17 01:02:31 +02:00
LOCPLINT - > localState - > erasePath ( town - > visitingHero ) ;
2018-04-07 13:34:11 +02:00
}
void CCastleInterface : : townChange ( )
{
2018-07-25 00:36:48 +02:00
//TODO: do not recreate window
2023-04-17 14:32:18 +02:00
const CGTownInstance * dest = LOCPLINT - > localState - > getOwnedTown ( townlist - > getSelectedIndex ( ) ) ;
2018-04-07 13:34:11 +02:00
const CGTownInstance * town = this - > town ; // "this" is going to be deleted
if ( dest = = town )
return ;
close ( ) ;
2023-05-16 15:20:35 +02:00
GH . windows ( ) . createAndPushWindow < CCastleInterface > ( dest , town ) ;
2018-04-07 13:34:11 +02:00
}
void CCastleInterface : : addBuilding ( BuildingID bid )
{
deactivate ( ) ;
builds - > addBuilding ( bid ) ;
recreateIcons ( ) ;
activate ( ) ;
2023-03-31 19:08:37 +02:00
redraw ( ) ;
2018-04-07 13:34:11 +02:00
}
void CCastleInterface : : removeBuilding ( BuildingID bid )
{
deactivate ( ) ;
builds - > removeBuilding ( bid ) ;
recreateIcons ( ) ;
activate ( ) ;
2023-03-31 19:08:37 +02:00
redraw ( ) ;
2018-04-07 13:34:11 +02:00
}
void CCastleInterface : : recreateIcons ( )
{
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2023-03-15 23:47:26 +02:00
size_t iconIndex = town - > town - > clientInfo . icons [ town - > hasFort ( ) ] [ town - > builded > = CGI - > settings ( ) - > getInteger ( EGameSettings : : TOWNS_BUILDINGS_PER_TURN_CAP ) ] ;
2018-04-07 13:34:11 +02:00
icon - > setFrame ( iconIndex ) ;
TResources townIncome = town - > dailyIncome ( ) ;
2023-04-05 02:26:29 +02:00
income - > setText ( std : : to_string ( townIncome [ EGameResID : : GOLD ] ) ) ;
2018-04-07 13:34:11 +02:00
hall = std : : make_shared < CTownInfo > ( 80 , 413 , town , true ) ;
fort = std : : make_shared < CTownInfo > ( 122 , 413 , town , false ) ;
2022-09-17 21:22:09 +02:00
fastArmyPurchase = std : : make_shared < CButton > ( Point ( 122 , 413 ) , " itmcl.def " , CButton : : tooltip ( ) , [ & ] ( ) { builds - > enterToTheQuickRecruitmentWindow ( ) ; } ) ;
fastArmyPurchase - > setImageOrder ( town - > fortLevel ( ) - 1 , town - > fortLevel ( ) - 1 , town - > fortLevel ( ) - 1 , town - > fortLevel ( ) - 1 ) ;
2022-09-17 14:44:13 +02:00
fastArmyPurchase - > setAnimateLonelyFrame ( true ) ;
2018-04-07 13:34:11 +02:00
creainfo . clear ( ) ;
2023-02-02 21:54:47 +02:00
bool compactCreatureInfo = useCompactCreatureBox ( ) ;
bool useAvailableCreaturesForLabel = useAvailableAmountAsCreatureLabel ( ) ;
2018-04-07 13:34:11 +02:00
for ( size_t i = 0 ; i < 4 ; i + + )
2023-02-05 21:24:36 +02:00
creainfo . push_back ( std : : make_shared < CCreaInfo > ( Point ( 14 + 55 * ( int ) i , 459 ) , town , ( int ) i , compactCreatureInfo , useAvailableCreaturesForLabel ) ) ;
2018-04-07 13:34:11 +02:00
for ( size_t i = 0 ; i < 4 ; i + + )
2023-02-05 21:24:36 +02:00
creainfo . push_back ( std : : make_shared < CCreaInfo > ( Point ( 14 + 55 * ( int ) i , 507 ) , town , ( int ) i + 4 , compactCreatureInfo , useAvailableCreaturesForLabel ) ) ;
2018-04-07 13:34:11 +02:00
}
2023-04-27 19:21:06 +02:00
void CCastleInterface : : keyPressed ( EShortcut key )
2018-04-07 13:34:11 +02:00
{
2023-02-02 18:02:25 +02:00
switch ( key )
2012-07-21 23:16:54 +03:00
{
2023-04-28 13:22:03 +02:00
case EShortcut : : MOVE_UP :
2018-04-07 13:34:11 +02:00
townlist - > selectPrev ( ) ;
break ;
2023-04-28 13:22:03 +02:00
case EShortcut : : MOVE_DOWN :
2018-04-07 13:34:11 +02:00
townlist - > selectNext ( ) ;
break ;
2023-04-27 19:21:06 +02:00
case EShortcut : : TOWN_SWAP_ARMIES :
2018-04-07 13:34:11 +02:00
heroes - > swapArmies ( ) ;
break ;
2023-04-27 19:21:06 +02:00
case EShortcut : : TOWN_OPEN_TAVERN :
2018-04-07 13:34:11 +02:00
if ( town - > hasBuilt ( BuildingID : : TAVERN ) )
LOCPLINT - > showTavernWindow ( town ) ;
break ;
default :
break ;
2012-07-21 23:16:54 +03:00
}
2018-04-07 13:34:11 +02:00
}
2023-02-02 21:54:47 +02:00
void CCastleInterface : : creaturesChangedEventHandler ( )
{
for ( auto creatureInfoBox : creainfo )
{
if ( creatureInfoBox - > getShowAvailable ( ) )
{
creatureInfoBox - > update ( ) ;
}
}
}
2018-04-07 13:34:11 +02:00
CHallInterface : : CBuildingBox : : CBuildingBox ( int x , int y , const CGTownInstance * Town , const CBuilding * Building ) :
town ( Town ) ,
building ( Building )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2023-06-13 18:33:35 +02:00
addUsedEvents ( LCLICK | SHOW_POPUP | HOVER ) ;
2018-04-07 13:34:11 +02:00
pos . x + = x ;
pos . y + = y ;
pos . w = 154 ;
pos . h = 92 ;
state = LOCPLINT - > cb - > canBuildStructure ( town , building - > bid ) ;
static int panelIndex [ 12 ] =
{
3 , 3 , 3 , 0 , 0 , 2 , 2 , 1 , 2 , 2 , 3 , 3
} ;
static int iconIndex [ 12 ] =
{
- 1 , - 1 , - 1 , 0 , 0 , 1 , 2 , - 1 , 1 , 1 , - 1 , - 1
} ;
icon = std : : make_shared < CAnimImage > ( town - > town - > clientInfo . buildingsIcons , building - > bid , 0 , 2 , 2 ) ;
header = std : : make_shared < CAnimImage > ( " TPTHBAR " , panelIndex [ state ] , 0 , 1 , 73 ) ;
if ( iconIndex [ state ] > = 0 )
mark = std : : make_shared < CAnimImage > ( " TPTHCHK " , iconIndex [ state ] , 0 , 136 , 56 ) ;
2023-01-04 15:17:50 +02:00
name = std : : make_shared < CLabel > ( 75 , 81 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , building - > getNameTranslated ( ) ) ;
2018-04-07 13:34:11 +02:00
//todo: add support for all possible states
if ( state > = EBuildingState : : BUILDING_ERROR )
state = EBuildingState : : FORBIDDEN ;
2012-07-21 23:16:54 +03:00
}
2008-03-10 01:06:35 +02:00
void CHallInterface : : CBuildingBox : : hover ( bool on )
{
2008-03-16 02:09:43 +02:00
if ( on )
{
2008-06-03 21:16:54 +03:00
std : : string toPrint ;
2013-12-02 14:58:02 +03:00
if ( state = = EBuildingState : : PREREQUIRES | | state = = EBuildingState : : MISSING_BASE )
2008-12-22 19:48:41 +02:00
toPrint = CGI - > generaltexth - > hcommands [ 5 ] ;
2011-12-14 00:23:17 +03:00
else if ( state = = EBuildingState : : CANT_BUILD_TODAY )
2009-12-23 03:46:15 +02:00
toPrint = CGI - > generaltexth - > allTexts [ 223 ] ;
2008-06-03 21:16:54 +03:00
else
2008-12-22 19:48:41 +02:00
toPrint = CGI - > generaltexth - > hcommands [ state ] ;
2023-01-04 15:17:50 +02:00
boost : : algorithm : : replace_first ( toPrint , " %s " , building - > getNameTranslated ( ) ) ;
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( toPrint ) ;
2008-03-16 02:09:43 +02:00
}
else
2018-04-07 13:34:11 +02:00
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2018-04-07 13:34:11 +02:00
}
2008-03-10 01:06:35 +02:00
}
2011-04-07 20:54:08 +03:00
2023-07-09 16:48:25 +02:00
void CHallInterface : : CBuildingBox : : clickPressed ( const Point & cursorPosition )
2008-03-10 01:06:35 +02:00
{
2023-07-08 13:33:04 +02:00
GH . windows ( ) . createAndPushWindow < CBuildWindow > ( town , building , state , 0 ) ;
2008-03-10 01:06:35 +02:00
}
2011-04-07 20:54:08 +03:00
2023-07-08 13:33:04 +02:00
void CHallInterface : : CBuildingBox : : showPopupWindow ( const Point & cursorPosition )
2008-03-10 01:06:35 +02:00
{
2023-06-11 17:20:10 +02:00
GH . windows ( ) . createAndPushWindow < CBuildWindow > ( town , building , state , 1 ) ;
2008-03-11 23:36:59 +02:00
}
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
CHallInterface : : CHallInterface ( const CGTownInstance * Town ) :
2018-10-29 15:12:07 +02:00
CStatusbarWindow ( PLAYER_COLORED | BORDERED , Town - > town - > clientInfo . hallBackground ) ,
2011-04-07 20:54:08 +03:00
town ( Town )
2008-03-10 01:06:35 +02:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
resdatabar = std : : make_shared < CMinorResDataBar > ( ) ;
resdatabar - > moveBy ( pos . topLeft ( ) , true ) ;
2013-12-02 14:58:02 +03:00
Rect barRect ( 5 , 556 , 740 , 18 ) ;
2023-01-30 13:58:13 +02:00
auto statusbarBackground = std : : make_shared < CPicture > ( background - > getSurface ( ) , barRect , 5 , 556 ) ;
2018-08-26 18:09:56 +02:00
statusbar = CGStatusBar : : create ( statusbarBackground ) ;
2018-04-07 13:34:11 +02:00
2023-01-04 15:17:50 +02:00
title = std : : make_shared < CLabel > ( 399 , 12 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , town - > town - > buildings . at ( BuildingID ( town - > hallLevel ( ) + BuildingID : : VILLAGE_HALL ) ) - > getNameTranslated ( ) ) ;
2023-04-27 19:21:06 +02:00
exit = std : : make_shared < CButton > ( Point ( 748 , 556 ) , " TPMAGE1.DEF " , CButton : : tooltip ( CGI - > generaltexth - > hcommands [ 8 ] ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_RETURN ) ;
2008-03-21 02:03:31 +02:00
2012-09-02 13:33:41 +03:00
auto & boxList = town - > town - > clientInfo . hallSlots ;
2011-04-07 20:54:08 +03:00
boxes . resize ( boxList . size ( ) ) ;
for ( size_t row = 0 ; row < boxList . size ( ) ; row + + ) //for each row
2008-03-11 23:36:59 +02:00
{
2011-04-07 20:54:08 +03:00
for ( size_t col = 0 ; col < boxList [ row ] . size ( ) ; col + + ) //for each box
2008-03-11 23:36:59 +02:00
{
2017-10-28 01:25:44 +02:00
const CBuilding * building = nullptr ;
for ( auto & buildingID : boxList [ row ] [ col ] ) //we are looking for the first not built structure
2013-12-02 14:58:02 +03:00
{
2017-10-28 01:25:44 +02:00
const CBuilding * current = town - > town - > buildings . at ( buildingID ) ;
if ( vstd : : contains ( town - > builtBuildings , buildingID ) )
{
building = current ;
}
else
{
if ( current - > mode = = CBuilding : : BUILD_NORMAL )
{
building = current ;
break ;
}
}
2008-03-11 23:36:59 +02:00
}
2020-10-01 10:38:06 +02:00
int posX = pos . w / 2 - ( int ) boxList [ row ] . size ( ) * 154 / 2 - ( ( int ) boxList [ row ] . size ( ) - 1 ) * 20 + 194 * ( int ) col ,
2020-10-06 01:27:04 +02:00
posY = 35 + 104 * ( int ) row ;
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
if ( building )
boxes [ row ] . push_back ( std : : make_shared < CBuildingBox > ( posX , posY , town , building ) ) ;
2008-03-11 23:36:59 +02:00
}
}
2008-03-10 01:06:35 +02:00
}
2009-04-14 15:47:09 +03:00
2018-04-07 13:34:11 +02:00
CBuildWindow : : CBuildWindow ( const CGTownInstance * Town , const CBuilding * Building , int state , bool rightClick ) :
2018-10-29 15:12:07 +02:00
CStatusbarWindow ( PLAYER_COLORED | ( rightClick ? RCLICK_POPUP : 0 ) , " TPUBUILD " ) ,
2018-04-07 13:34:11 +02:00
town ( Town ) ,
building ( Building )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
icon = std : : make_shared < CAnimImage > ( town - > town - > clientInfo . buildingsIcons , building - > bid , 0 , 125 , 50 ) ;
2022-11-29 17:07:21 +02:00
auto statusbarBackground = std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ;
2018-08-26 18:09:56 +02:00
statusbar = CGStatusBar : : create ( statusbarBackground ) ;
2018-04-07 13:34:11 +02:00
2023-08-10 20:23:18 +02:00
MetaString nameString ;
nameString . appendTextID ( " core.hallinfo.7 " ) ;
nameString . replaceTextID ( building - > getNameTextID ( ) ) ;
name = std : : make_shared < CLabel > ( 197 , 30 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , nameString . toString ( ) ) ;
2023-01-04 15:17:50 +02:00
description = std : : make_shared < CTextBox > ( building - > getDescriptionTranslated ( ) , Rect ( 33 , 135 , 329 , 67 ) , 0 , FONT_MEDIUM , ETextAlignment : : CENTER ) ;
2022-11-26 23:12:20 +02:00
stateText = std : : make_shared < CTextBox > ( getTextForState ( state ) , Rect ( 33 , 216 , 329 , 67 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER ) ;
2018-04-07 13:34:11 +02:00
//Create components for all required resources
std : : vector < std : : shared_ptr < CComponent > > components ;
for ( int i = 0 ; i < GameConstants : : RESOURCE_QUANTITY ; i + + )
{
if ( building - > resources [ i ] )
components . push_back ( std : : make_shared < CComponent > ( CComponent : : resource , i , building - > resources [ i ] , CComponent : : small ) ) ;
}
cost = std : : make_shared < CComponentBox > ( components , Rect ( 25 , 300 , pos . w - 50 , 130 ) ) ;
if ( ! rightClick )
{ //normal window
2023-08-10 20:23:18 +02:00
MetaString tooltipYes ;
tooltipYes . appendTextID ( " core.genrltxt.595 " ) ;
tooltipYes . replaceTextID ( building - > getNameTextID ( ) ) ;
MetaString tooltipNo ;
tooltipNo . appendTextID ( " core.genrltxt.596 " ) ;
tooltipNo . replaceTextID ( building - > getNameTextID ( ) ) ;
buy = std : : make_shared < CButton > ( Point ( 45 , 446 ) , " IBUY30 " , CButton : : tooltip ( tooltipYes . toString ( ) ) , [ & ] ( ) { buyFunc ( ) ; } , EShortcut : : GLOBAL_ACCEPT ) ;
2018-04-07 13:34:11 +02:00
buy - > setBorderColor ( Colors : : METALLIC_GOLD ) ;
buy - > block ( state ! = 7 | | LOCPLINT - > playerID ! = town - > tempOwner ) ;
2023-08-10 20:23:18 +02:00
cancel = std : : make_shared < CButton > ( Point ( 290 , 445 ) , " ICANCEL " , CButton : : tooltip ( tooltipNo . toString ( ) ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_CANCEL ) ;
2018-04-07 13:34:11 +02:00
cancel - > setBorderColor ( Colors : : METALLIC_GOLD ) ;
}
}
2011-04-07 20:54:08 +03:00
void CBuildWindow : : buyFunc ( )
2008-03-21 02:03:31 +02:00
{
2011-04-07 20:54:08 +03:00
LOCPLINT - > cb - > buildBuilding ( town , building - > bid ) ;
2023-05-16 15:20:35 +02:00
GH . windows ( ) . popWindows ( 2 ) ; //we - build window and hall screen
2008-03-21 02:03:31 +02:00
}
2009-04-14 15:47:09 +03:00
2011-04-07 20:54:08 +03:00
std : : string CBuildWindow : : getTextForState ( int state )
2008-03-21 02:03:31 +02:00
{
2008-03-23 03:01:17 +02:00
std : : string ret ;
2013-12-02 14:58:02 +03:00
if ( state < EBuildingState : : ALLOWED )
2008-12-22 19:48:41 +02:00
ret = CGI - > generaltexth - > hcommands [ state ] ;
2008-03-21 02:03:31 +02:00
switch ( state )
{
2013-12-02 14:58:02 +03:00
case EBuildingState : : ALREADY_PRESENT :
case EBuildingState : : CANT_BUILD_TODAY :
case EBuildingState : : NO_RESOURCES :
2023-01-04 15:17:50 +02:00
ret . replace ( ret . find_first_of ( " %s " ) , 2 , building - > getNameTranslated ( ) ) ;
2008-03-23 03:01:17 +02:00
break ;
2013-12-02 14:58:02 +03:00
case EBuildingState : : ALLOWED :
2008-03-21 02:03:31 +02:00
return CGI - > generaltexth - > allTexts [ 219 ] ; //all prereq. are met
2013-12-02 14:58:02 +03:00
case EBuildingState : : PREREQUIRES :
2008-03-23 03:01:17 +02:00
{
2013-12-02 14:58:02 +03:00
auto toStr = [ & ] ( const BuildingID build ) - > std : : string
{
2023-01-04 15:17:50 +02:00
return town - > town - > buildings . at ( build ) - > getNameTranslated ( ) ;
2013-12-02 14:58:02 +03:00
} ;
2008-03-23 03:01:17 +02:00
ret = CGI - > generaltexth - > allTexts [ 52 ] ;
2016-08-30 20:53:56 +02:00
ret + = " \n " + town - > genBuildingRequirements ( building - > bid ) . toString ( toStr ) ;
2013-12-02 14:58:02 +03:00
break ;
}
case EBuildingState : : MISSING_BASE :
{
2022-12-27 22:19:05 +02:00
std : : string msg = CGI - > generaltexth - > translate ( " vcmi.townHall.missingBase " ) ;
2023-01-04 15:17:50 +02:00
ret = boost : : str ( boost : : format ( msg ) % town - > town - > buildings . at ( building - > upgrade ) - > getNameTranslated ( ) ) ;
2013-12-02 14:58:02 +03:00
break ;
}
2008-03-21 02:03:31 +02:00
}
2008-03-23 03:01:17 +02:00
return ret ;
2008-03-16 02:09:43 +02:00
}
2009-04-14 15:47:09 +03:00
2018-04-07 13:34:11 +02:00
LabeledValue : : LabeledValue ( Rect size , std : : string name , std : : string descr , int min , int max )
2011-04-07 20:54:08 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
pos . x + = size . x ;
pos . y + = size . y ;
pos . w = size . w ;
pos . h = size . h ;
init ( name , descr , min , max ) ;
}
2012-07-07 16:32:37 +03:00
2018-04-07 13:34:11 +02:00
LabeledValue : : LabeledValue ( Rect size , std : : string name , std : : string descr , int val )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
pos . x + = size . x ;
pos . y + = size . y ;
pos . w = size . w ;
pos . h = size . h ;
init ( name , descr , val , val ) ;
}
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
void LabeledValue : : init ( std : : string nameText , std : : string descr , int min , int max )
{
addUsedEvents ( HOVER ) ;
hoverText = descr ;
std : : string valueText ;
if ( min & & max )
2008-12-23 15:59:03 +02:00
{
2023-03-09 15:36:46 +02:00
valueText = std : : to_string ( min ) ;
2018-04-07 13:34:11 +02:00
if ( min ! = max )
2023-03-09 15:36:46 +02:00
valueText + = ' - ' + std : : to_string ( max ) ;
2008-03-23 03:01:17 +02:00
}
2022-11-26 23:12:20 +02:00
name = std : : make_shared < CLabel > ( 3 , 0 , FONT_SMALL , ETextAlignment : : TOPLEFT , Colors : : WHITE , nameText ) ;
value = std : : make_shared < CLabel > ( pos . w - 3 , pos . h - 2 , FONT_SMALL , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE , valueText ) ;
2008-03-16 02:09:43 +02:00
}
2009-04-14 15:47:09 +03:00
2018-04-07 13:34:11 +02:00
void LabeledValue : : hover ( bool on )
2011-04-07 20:54:08 +03:00
{
2018-04-07 13:34:11 +02:00
if ( on )
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( hoverText ) ;
2018-04-07 13:34:11 +02:00
}
2012-06-02 18:16:54 +03:00
else
2018-04-07 13:34:11 +02:00
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2018-04-07 13:34:11 +02:00
}
2011-04-07 20:54:08 +03:00
}
2012-06-02 18:16:54 +03:00
CFortScreen : : CFortScreen ( const CGTownInstance * town ) :
2018-10-29 15:12:07 +02:00
CStatusbarWindow ( PLAYER_COLORED | BORDERED , getBgName ( town ) )
2008-03-16 02:09:43 +02:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2020-10-01 10:38:06 +02:00
ui32 fortSize = static_cast < ui32 > ( town - > creatures . size ( ) ) ;
2018-04-07 13:34:11 +02:00
if ( fortSize > GameConstants : : CREATURES_PER_TOWN & & town - > creatures . back ( ) . second . empty ( ) )
2013-12-02 14:58:02 +03:00
fortSize - - ;
2014-03-07 16:21:09 +03:00
2018-04-07 13:34:11 +02:00
const CBuilding * fortBuilding = town - > town - > buildings . at ( BuildingID ( town - > fortLevel ( ) + 6 ) ) ;
2023-01-04 15:17:50 +02:00
title = std : : make_shared < CLabel > ( 400 , 12 , FONT_BIG , ETextAlignment : : CENTER , Colors : : WHITE , fortBuilding - > getNameTranslated ( ) ) ;
2014-03-07 16:21:09 +03:00
2023-01-04 15:17:50 +02:00
std : : string text = boost : : str ( boost : : format ( CGI - > generaltexth - > fcommands [ 6 ] ) % fortBuilding - > getNameTranslated ( ) ) ;
2023-04-27 19:21:06 +02:00
exit = std : : make_shared < CButton > ( Point ( 748 , 556 ) , " TPMAGE1 " , CButton : : tooltip ( text ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_RETURN ) ;
2011-04-07 20:54:08 +03:00
2014-10-03 23:34:13 +03:00
std : : vector < Point > positions =
{
Point ( 10 , 22 ) , Point ( 404 , 22 ) ,
Point ( 10 , 155 ) , Point ( 404 , 155 ) ,
Point ( 10 , 288 ) , Point ( 404 , 288 )
} ;
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
if ( fortSize = = GameConstants : : CREATURES_PER_TOWN )
{
2014-10-03 23:34:13 +03:00
positions . push_back ( Point ( 206 , 421 ) ) ;
2018-04-07 13:34:11 +02:00
}
2011-04-07 20:54:08 +03:00
else
2014-10-03 23:34:13 +03:00
{
positions . push_back ( Point ( 10 , 421 ) ) ;
positions . push_back ( Point ( 404 , 421 ) ) ;
2016-10-16 02:00:57 +02:00
}
2014-03-07 16:21:09 +03:00
2018-04-07 13:34:11 +02:00
for ( ui32 i = 0 ; i < fortSize ; i + + )
2008-03-23 03:01:17 +02:00
{
2013-02-11 22:11:34 +03:00
BuildingID buildingID ;
2018-04-07 13:34:11 +02:00
if ( fortSize = = GameConstants : : CREATURES_PER_TOWN )
2011-04-07 20:54:08 +03:00
{
2018-04-07 13:34:11 +02:00
if ( vstd : : contains ( town - > builtBuildings , BuildingID : : DWELL_UP_FIRST + i ) )
2013-02-11 22:11:34 +03:00
buildingID = BuildingID ( BuildingID : : DWELL_UP_FIRST + i ) ;
2011-04-07 20:54:08 +03:00
else
2013-02-11 22:11:34 +03:00
buildingID = BuildingID ( BuildingID : : DWELL_FIRST + i ) ;
2011-04-07 20:54:08 +03:00
}
else
2018-04-07 13:34:11 +02:00
{
2013-02-11 22:11:34 +03:00
buildingID = BuildingID : : SPECIAL_3 ;
2018-04-07 13:34:11 +02:00
}
recAreas . push_back ( std : : make_shared < RecruitArea > ( positions [ i ] . x , positions [ i ] . y , town , i ) ) ;
2008-03-23 03:01:17 +02:00
}
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
resdatabar = std : : make_shared < CMinorResDataBar > ( ) ;
resdatabar - > moveBy ( pos . topLeft ( ) , true ) ;
2011-04-07 20:54:08 +03:00
2011-12-22 16:05:19 +03:00
Rect barRect ( 4 , 554 , 740 , 18 ) ;
2008-08-17 12:11:16 +03:00
2023-01-30 13:58:13 +02:00
auto statusbarBackground = std : : make_shared < CPicture > ( background - > getSurface ( ) , barRect , 4 , 554 ) ;
2018-08-26 18:09:56 +02:00
statusbar = CGStatusBar : : create ( statusbarBackground ) ;
2008-08-17 12:11:16 +03:00
}
2018-04-07 13:34:11 +02:00
std : : string CFortScreen : : getBgName ( const CGTownInstance * town )
2011-02-06 19:26:27 +02:00
{
2020-10-01 10:38:06 +02:00
ui32 fortSize = static_cast < ui32 > ( town - > creatures . size ( ) ) ;
2018-04-07 13:34:11 +02:00
if ( fortSize > GameConstants : : CREATURES_PER_TOWN & & town - > creatures . back ( ) . second . empty ( ) )
fortSize - - ;
2008-08-17 12:11:16 +03:00
2018-04-07 13:34:11 +02:00
if ( fortSize = = GameConstants : : CREATURES_PER_TOWN )
return " TPCASTL7 " ;
2011-04-07 20:54:08 +03:00
else
2018-04-07 13:34:11 +02:00
return " TPCASTL8 " ;
2014-01-11 21:12:09 +03:00
}
2023-02-02 21:54:47 +02:00
void CFortScreen : : creaturesChangedEventHandler ( )
2014-01-11 21:12:09 +03:00
{
2018-04-07 13:34:11 +02:00
for ( auto & elem : recAreas )
2023-02-02 21:54:47 +02:00
elem - > creaturesChangedEventHandler ( ) ;
LOCPLINT - > castleInt - > creaturesChangedEventHandler ( ) ;
2014-01-11 21:12:09 +03:00
}
2018-04-07 13:34:11 +02:00
CFortScreen : : RecruitArea : : RecruitArea ( int posX , int posY , const CGTownInstance * Town , int Level ) :
2011-04-07 20:54:08 +03:00
town ( Town ) ,
level ( Level ) ,
2013-06-26 14:18:27 +03:00
availableCount ( nullptr )
2008-08-17 12:11:16 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2011-04-07 20:54:08 +03:00
pos . x + = posX ;
pos . y + = posY ;
pos . w = 386 ;
pos . h = 126 ;
2014-03-07 16:21:09 +03:00
2018-04-07 13:34:11 +02:00
if ( ! town - > creatures [ level ] . second . empty ( ) )
2023-06-11 17:20:10 +02:00
addUsedEvents ( LCLICK | HOVER ) ; //Activate only if dwelling is present
2014-03-07 16:21:09 +03:00
2023-07-30 14:29:18 +02:00
addUsedEvents ( SHOW_POPUP ) ;
2018-04-07 13:34:11 +02:00
icons = std : : make_shared < CPicture > ( " TPCAINFO " , 261 , 3 ) ;
2016-11-27 18:00:16 +02:00
2018-04-07 13:34:11 +02:00
if ( getMyBuilding ( ) ! = nullptr )
2014-01-11 21:12:09 +03:00
{
2018-04-07 13:34:11 +02:00
buildingIcon = std : : make_shared < CAnimImage > ( town - > town - > clientInfo . buildingsIcons , getMyBuilding ( ) - > bid , 0 , 4 , 21 ) ;
2023-01-04 15:17:50 +02:00
buildingName = std : : make_shared < CLabel > ( 78 , 101 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , getMyBuilding ( ) - > getNameTranslated ( ) ) ;
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
if ( vstd : : contains ( town - > builtBuildings , getMyBuilding ( ) - > bid ) )
2014-01-11 21:12:09 +03:00
{
ui32 available = town - > creatures [ level ] . first ;
2023-03-09 15:36:46 +02:00
std : : string availableText = CGI - > generaltexth - > allTexts [ 217 ] + std : : to_string ( available ) ;
2022-11-26 23:12:20 +02:00
availableCount = std : : make_shared < CLabel > ( 78 , 119 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , availableText ) ;
2014-01-11 21:12:09 +03:00
}
}
2011-04-07 20:54:08 +03:00
2018-04-07 13:34:11 +02:00
if ( getMyCreature ( ) ! = nullptr )
2013-12-02 14:58:02 +03:00
{
2023-01-02 18:00:51 +02:00
hoverText = boost : : str ( boost : : format ( CGI - > generaltexth - > tcommands [ 21 ] ) % getMyCreature ( ) - > getNamePluralTranslated ( ) ) ;
2016-11-27 18:00:16 +02:00
new CCreaturePic ( 159 , 4 , getMyCreature ( ) , false ) ;
2023-01-02 18:00:51 +02:00
new CLabel ( 78 , 11 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , getMyCreature ( ) - > getNamePluralTranslated ( ) ) ;
2014-01-11 21:12:09 +03:00
Rect sizes ( 287 , 4 , 96 , 18 ) ;
2018-04-07 13:34:11 +02:00
values . push_back ( std : : make_shared < LabeledValue > ( sizes , CGI - > generaltexth - > allTexts [ 190 ] , CGI - > generaltexth - > fcommands [ 0 ] , getMyCreature ( ) - > getAttack ( false ) ) ) ;
2014-01-11 21:12:09 +03:00
sizes . y + = 20 ;
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
values . push_back ( std : : make_shared < LabeledValue > ( sizes , CGI - > generaltexth - > allTexts [ 191 ] , CGI - > generaltexth - > fcommands [ 1 ] , getMyCreature ( ) - > getDefense ( false ) ) ) ;
2014-01-11 21:12:09 +03:00
sizes . y + = 21 ;
2018-04-07 13:34:11 +02:00
values . push_back ( std : : make_shared < LabeledValue > ( sizes , CGI - > generaltexth - > allTexts [ 199 ] , CGI - > generaltexth - > fcommands [ 2 ] , getMyCreature ( ) - > getMinDamage ( false ) , getMyCreature ( ) - > getMaxDamage ( false ) ) ) ;
2014-01-11 21:12:09 +03:00
sizes . y + = 20 ;
2023-05-01 19:29:53 +02:00
values . push_back ( std : : make_shared < LabeledValue > ( sizes , CGI - > generaltexth - > allTexts [ 388 ] , CGI - > generaltexth - > fcommands [ 3 ] , getMyCreature ( ) - > getMaxHealth ( ) ) ) ;
2014-01-11 21:12:09 +03:00
sizes . y + = 21 ;
2023-05-01 00:20:01 +02:00
values . push_back ( std : : make_shared < LabeledValue > ( sizes , CGI - > generaltexth - > allTexts [ 193 ] , CGI - > generaltexth - > fcommands [ 4 ] , getMyCreature ( ) - > valOfBonuses ( BonusType : : STACKS_SPEED ) ) ) ;
2014-01-11 21:12:09 +03:00
sizes . y + = 20 ;
2018-04-07 13:34:11 +02:00
values . push_back ( std : : make_shared < LabeledValue > ( sizes , CGI - > generaltexth - > allTexts [ 194 ] , CGI - > generaltexth - > fcommands [ 5 ] , town - > creatureGrowth ( level ) ) ) ;
2011-04-07 20:54:08 +03:00
}
2008-08-17 12:11:16 +03:00
}
2009-04-14 15:47:09 +03:00
2018-04-07 13:34:11 +02:00
const CCreature * CFortScreen : : RecruitArea : : getMyCreature ( )
{
if ( ! town - > creatures . at ( level ) . second . empty ( ) ) // built
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
return VLC - > creh - > objects [ town - > creatures . at ( level ) . second . back ( ) ] ;
2018-04-07 13:34:11 +02:00
if ( ! town - > town - > creatures . at ( level ) . empty ( ) ) // there are creatures on this level
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
return VLC - > creh - > objects [ town - > town - > creatures . at ( level ) . front ( ) ] ;
2018-04-07 13:34:11 +02:00
return nullptr ;
}
const CBuilding * CFortScreen : : RecruitArea : : getMyBuilding ( )
{
BuildingID myID = BuildingID ( BuildingID : : DWELL_FIRST ) . advance ( level ) ;
if ( level = = GameConstants : : CREATURES_PER_TOWN )
2020-10-15 14:03:01 +02:00
return town - > town - > getSpecialBuilding ( BuildingSubID : : PORTAL_OF_SUMMONING ) ;
2018-04-07 13:34:11 +02:00
if ( ! town - > town - > buildings . count ( myID ) )
return nullptr ;
const CBuilding * build = town - > town - > buildings . at ( myID ) ;
while ( town - > town - > buildings . count ( myID ) )
{
if ( town - > hasBuilt ( myID ) )
build = town - > town - > buildings . at ( myID ) ;
myID . advance ( GameConstants : : CREATURES_PER_TOWN ) ;
}
return build ;
}
2011-04-07 20:54:08 +03:00
void CFortScreen : : RecruitArea : : hover ( bool on )
2008-08-17 12:11:16 +03:00
{
2011-04-07 20:54:08 +03:00
if ( on )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( hoverText ) ;
2010-07-26 01:47:59 +03:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2008-08-17 12:11:16 +03:00
}
2023-02-02 21:54:47 +02:00
void CFortScreen : : RecruitArea : : creaturesChangedEventHandler ( )
2008-08-17 12:11:16 +03:00
{
2018-04-07 13:34:11 +02:00
if ( availableCount )
2008-08-17 12:11:16 +03:00
{
2023-03-09 15:36:46 +02:00
std : : string availableText = CGI - > generaltexth - > allTexts [ 217 ] + std : : to_string ( town - > creatures [ level ] . first ) ;
2013-08-29 16:46:27 +03:00
availableCount - > setText ( availableText ) ;
2008-08-17 12:11:16 +03:00
}
}
2011-04-07 20:54:08 +03:00
2023-07-09 16:48:25 +02:00
void CFortScreen : : RecruitArea : : clickPressed ( const Point & cursorPosition )
2008-08-17 12:11:16 +03:00
{
2023-07-08 13:33:04 +02:00
LOCPLINT - > castleInt - > builds - > enterDwelling ( level ) ;
2008-08-17 12:11:16 +03:00
}
2008-08-20 09:57:53 +03:00
2023-07-30 14:29:18 +02:00
void CFortScreen : : RecruitArea : : showPopupWindow ( const Point & cursorPosition )
{
if ( getMyCreature ( ) ! = nullptr )
GH . windows ( ) . createAndPushWindow < CStackWindow > ( getMyCreature ( ) , true ) ;
}
2018-04-07 13:34:11 +02:00
CMageGuildScreen : : CMageGuildScreen ( CCastleInterface * owner , std : : string imagem )
2018-10-29 15:12:07 +02:00
: CStatusbarWindow ( BORDERED , imagem )
2008-08-20 09:57:53 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
window = std : : make_shared < CPicture > ( owner - > town - > town - > clientInfo . guildWindow , 332 , 76 ) ;
2014-03-07 16:21:09 +03:00
2018-04-07 13:34:11 +02:00
resdatabar = std : : make_shared < CMinorResDataBar > ( ) ;
resdatabar - > moveBy ( pos . topLeft ( ) , true ) ;
2014-03-07 16:21:09 +03:00
2011-12-22 16:05:19 +03:00
Rect barRect ( 7 , 556 , 737 , 18 ) ;
2014-03-07 16:21:09 +03:00
2023-01-30 13:58:13 +02:00
auto statusbarBackground = std : : make_shared < CPicture > ( background - > getSurface ( ) , barRect , 7 , 556 ) ;
2018-08-26 18:09:56 +02:00
statusbar = CGStatusBar : : create ( statusbarBackground ) ;
2018-04-07 13:34:11 +02:00
2023-04-27 19:21:06 +02:00
exit = std : : make_shared < CButton > ( Point ( 748 , 556 ) , " TPMAGE1.DEF " , CButton : : tooltip ( CGI - > generaltexth - > allTexts [ 593 ] ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_RETURN ) ;
2014-03-07 16:21:09 +03:00
2016-10-16 02:00:57 +02:00
static const std : : vector < std : : vector < Point > > positions =
2014-10-03 23:34:13 +03:00
{
{ Point ( 222 , 445 ) , Point ( 312 , 445 ) , Point ( 402 , 445 ) , Point ( 520 , 445 ) , Point ( 610 , 445 ) , Point ( 700 , 445 ) } ,
{ Point ( 48 , 53 ) , Point ( 48 , 147 ) , Point ( 48 , 241 ) , Point ( 48 , 335 ) , Point ( 48 , 429 ) } ,
{ Point ( 570 , 82 ) , Point ( 672 , 82 ) , Point ( 570 , 157 ) , Point ( 672 , 157 ) } ,
{ Point ( 183 , 42 ) , Point ( 183 , 148 ) , Point ( 183 , 253 ) } ,
{ Point ( 491 , 325 ) , Point ( 591 , 325 ) }
} ;
2014-03-07 16:21:09 +03:00
2008-12-21 21:17:35 +02:00
for ( size_t i = 0 ; i < owner - > town - > town - > mageLevel ; i + + )
2008-08-20 09:57:53 +03:00
{
2020-10-01 10:38:06 +02:00
size_t spellCount = owner - > town - > spellsAtLevel ( ( int ) i + 1 , false ) ; //spell at level with -1 hmmm?
2011-04-07 20:54:08 +03:00
for ( size_t j = 0 ; j < spellCount ; j + + )
2008-08-20 09:57:53 +03:00
{
2008-09-23 13:58:54 +03:00
if ( i < owner - > town - > mageGuildLevel ( ) & & owner - > town - > spells [ i ] . size ( ) > j )
2018-04-07 13:34:11 +02:00
spells . push_back ( std : : make_shared < Scroll > ( positions [ i ] [ j ] , CGI - > spellh - > objects [ owner - > town - > spells [ i ] [ j ] ] ) ) ;
2008-08-20 09:57:53 +03:00
else
2018-04-07 13:34:11 +02:00
emptyScrolls . push_back ( std : : make_shared < CAnimImage > ( " TPMAGES.DEF " , 1 , 0 , positions [ i ] [ j ] . x , positions [ i ] [ j ] . y ) ) ;
2008-08-20 09:57:53 +03:00
}
}
}
2009-04-14 15:47:09 +03:00
2011-12-22 16:05:19 +03:00
CMageGuildScreen : : Scroll : : Scroll ( Point position , const CSpell * Spell )
2018-04-07 13:34:11 +02:00
: spell ( Spell )
2008-08-20 09:57:53 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2023-06-13 18:33:35 +02:00
addUsedEvents ( LCLICK | SHOW_POPUP | HOVER ) ;
2011-04-07 20:54:08 +03:00
pos + = position ;
2018-04-07 13:34:11 +02:00
image = std : : make_shared < CAnimImage > ( " SPELLSCR " , spell - > id ) ;
2011-04-07 20:54:08 +03:00
pos = image - > pos ;
2008-08-20 09:57:53 +03:00
}
2009-04-14 15:47:09 +03:00
2023-07-08 13:33:04 +02:00
void CMageGuildScreen : : Scroll : : clickPressed ( const Point & cursorPosition )
2008-08-20 09:57:53 +03:00
{
2023-07-08 13:33:04 +02:00
LOCPLINT - > showInfoDialog ( spell - > getDescriptionTranslated ( 0 ) , std : : make_shared < CComponent > ( CComponent : : spell , spell - > id ) ) ;
2008-08-20 09:57:53 +03:00
}
2009-04-14 15:47:09 +03:00
2023-07-08 13:33:04 +02:00
void CMageGuildScreen : : Scroll : : showPopupWindow ( const Point & cursorPosition )
2008-08-20 09:57:53 +03:00
{
2023-06-11 17:20:10 +02:00
CRClickPopup : : createAndPush ( spell - > getDescriptionTranslated ( 0 ) , std : : make_shared < CComponent > ( CComponent : : spell , spell - > id ) ) ;
2008-08-20 09:57:53 +03:00
}
2009-04-14 15:47:09 +03:00
2008-08-20 09:57:53 +03:00
void CMageGuildScreen : : Scroll : : hover ( bool on )
{
2008-08-27 13:19:18 +03:00
if ( on )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( spell - > getNameTranslated ( ) ) ;
2008-08-27 13:19:18 +03:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2008-08-20 09:57:53 +03:00
}
2009-04-14 15:47:09 +03:00
2013-02-14 02:55:42 +03:00
CBlacksmithDialog : : CBlacksmithDialog ( bool possible , CreatureID creMachineID , ArtifactID aid , ObjectInstanceID hid ) :
2018-10-29 15:12:07 +02:00
CStatusbarWindow ( PLAYER_COLORED , " TPSMITH " )
2008-08-27 13:19:18 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
Rect barRect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) ;
2011-04-07 20:54:08 +03:00
2023-01-30 13:58:13 +02:00
auto statusbarBackground = std : : make_shared < CPicture > ( background - > getSurface ( ) , barRect , 8 , pos . h - 26 ) ;
2018-08-26 18:09:56 +02:00
statusbar = CGStatusBar : : create ( statusbarBackground ) ;
2014-03-07 16:21:09 +03:00
2018-04-07 13:34:11 +02:00
animBG = std : : make_shared < CPicture > ( " TPSMITBK " , 64 , 50 ) ;
2011-02-06 19:26:27 +02:00
animBG - > needRefresh = true ;
2009-05-07 20:20:41 +03:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const CCreature * creature = CGI - > creh - > objects [ creMachineID ] ;
2018-07-25 00:36:48 +02:00
anim = std : : make_shared < CCreatureAnim > ( 64 , 50 , creature - > animDefName ) ;
2011-02-06 19:26:27 +02:00
anim - > clipRect ( 113 , 125 , 200 , 150 ) ;
2014-03-07 16:21:09 +03:00
2023-08-10 20:23:18 +02:00
MetaString titleString ;
titleString . appendTextID ( " core.genrltxt.274 " ) ;
titleString . replaceTextID ( creature - > getNameSingularTextID ( ) ) ;
2011-04-07 20:54:08 +03:00
2023-08-10 20:23:18 +02:00
MetaString buyText ;
buyText . appendTextID ( " core.genrltxt.595 " ) ;
buyText . replaceTextID ( creature - > getNameSingularTextID ( ) ) ;
2011-04-07 20:54:08 +03:00
2023-08-10 20:23:18 +02:00
MetaString cancelText ;
cancelText . appendTextID ( " core.genrltxt.596 " ) ;
cancelText . replaceTextID ( creature - > getNameSingularTextID ( ) ) ;
2014-03-07 16:21:09 +03:00
2023-08-10 20:23:18 +02:00
std : : string costString = std : : to_string ( aid . toArtifact ( CGI - > artifacts ( ) ) - > getPrice ( ) ) ;
title = std : : make_shared < CLabel > ( 165 , 28 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , titleString . toString ( ) ) ;
costText = std : : make_shared < CLabel > ( 165 , 218 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > jktexts [ 43 ] ) ;
costValue = std : : make_shared < CLabel > ( 165 , 292 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE , costString ) ;
buy = std : : make_shared < CButton > ( Point ( 42 , 312 ) , " IBUY30.DEF " , CButton : : tooltip ( buyText . toString ( ) ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_ACCEPT ) ;
cancel = std : : make_shared < CButton > ( Point ( 224 , 312 ) , " ICANCEL.DEF " , CButton : : tooltip ( cancelText . toString ( ) ) , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_CANCEL ) ;
2009-05-07 20:20:41 +03:00
2008-08-27 13:19:18 +03:00
if ( possible )
2017-07-19 01:06:05 +02:00
buy - > addCallback ( [ = ] ( ) { LOCPLINT - > cb - > buyArtifact ( LOCPLINT - > cb - > getHero ( hid ) , aid ) ; } ) ;
2008-08-27 13:19:18 +03:00
else
2011-04-07 20:54:08 +03:00
buy - > block ( true ) ;
2008-08-27 13:19:18 +03:00
2023-04-05 02:26:29 +02:00
costIcon = std : : make_shared < CAnimImage > ( " RESOURCE " , GameResID ( EGameResID : : GOLD ) , 0 , 148 , 244 ) ;
2008-08-27 13:19:18 +03:00
}