2017-07-13 10:26:03 +02:00
/*
2022-12-11 23:16:23 +02:00
* BattleInterfaceClasses . cpp , part of VCMI engine
2017-07-13 10:26:03 +02:00
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2011-12-22 16:05:19 +03:00
# include "StdInc.h"
2022-12-09 13:38:46 +02:00
# include "BattleInterfaceClasses.h"
2011-12-22 16:05:19 +03:00
2022-12-09 13:38:46 +02:00
# include "BattleInterface.h"
# include "BattleActionsController.h"
2022-12-21 17:02:53 +02:00
# include "BattleRenderer.h"
2022-12-09 13:38:46 +02:00
# include "BattleSiegeController.h"
# include "BattleFieldController.h"
# include "BattleStacksController.h"
2022-12-21 17:06:47 +02:00
# include "BattleWindow.h"
2014-07-13 20:53:37 +03:00
# include "../CGameInfo.h"
# include "../CMusicHandler.h"
2011-12-22 16:05:19 +03:00
# include "../CPlayerInterface.h"
2014-07-13 20:53:37 +03:00
# include "../CVideoHandler.h"
2023-01-05 19:34:37 +02:00
# include "../gui/CursorHandler.h"
2013-04-07 14:52:07 +03:00
# include "../gui/CGuiHandler.h"
2023-02-01 20:42:06 +02:00
# include "../render/Canvas.h"
# include "../render/IImage.h"
2014-07-15 10:14:49 +03:00
# include "../widgets/Buttons.h"
2022-11-24 16:30:04 +02:00
# include "../widgets/Images.h"
2014-07-15 10:14:49 +03:00
# include "../widgets/TextControls.h"
2023-02-01 20:42:06 +02:00
# include "../windows/CMessage.h"
2014-07-13 20:53:37 +03:00
# include "../windows/CSpellWindow.h"
2023-02-01 20:42:06 +02:00
# include "../render/CAnimation.h"
# include "../adventureMap/CInGameConsole.h"
2014-07-13 20:53:37 +03:00
# include "../../CCallback.h"
2017-03-17 17:48:44 +02:00
# include "../../lib/CStack.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/CConfigHandler.h"
# include "../../lib/CCreatureHandler.h"
2014-07-15 10:14:49 +03:00
# include "../../lib/CGameState.h"
2011-12-22 16:05:19 +03:00
# include "../../lib/CGeneralTextHandler.h"
2014-07-13 20:53:37 +03:00
# include "../../lib/CTownHandler.h"
2022-12-21 01:08:56 +02:00
# include "../../lib/CHeroHandler.h"
2011-12-22 16:05:19 +03:00
# include "../../lib/NetPacks.h"
2014-06-25 17:11:07 +03:00
# include "../../lib/StartInfo.h"
2014-07-15 10:14:49 +03:00
# include "../../lib/CondSh.h"
2015-12-02 21:05:10 +02:00
# include "../../lib/mapObjects/CGTownInstance.h"
2011-12-22 16:05:19 +03:00
2023-01-30 19:55:32 +02:00
# include <SDL_surface.h>
# include <SDL_events.h>
2022-12-09 13:26:17 +02:00
void BattleConsole : : showAll ( SDL_Surface * to )
2011-12-22 16:05:19 +03:00
{
2022-12-21 17:02:53 +02:00
CIntObject : : showAll ( to ) ;
2023-01-09 17:25:18 +02:00
Point line1 ( pos . x + pos . w / 2 , pos . y + 8 ) ;
Point line2 ( pos . x + pos . w / 2 , pos . y + 24 ) ;
2012-12-19 20:24:53 +03:00
2023-01-09 17:25:18 +02:00
auto visibleText = getVisibleText ( ) ;
if ( visibleText . size ( ) > 0 )
graphics - > fonts [ FONT_SMALL ] - > renderTextCenter ( to , visibleText [ 0 ] , Colors : : WHITE , line1 ) ;
if ( visibleText . size ( ) > 1 )
graphics - > fonts [ FONT_SMALL ] - > renderTextCenter ( to , visibleText [ 1 ] , Colors : : WHITE , line2 ) ;
}
std : : vector < std : : string > BattleConsole : : getVisibleText ( )
{
// high priority texts that hide battle log entries
for ( auto const & text : { consoleText , hoverText } )
2011-12-22 16:05:19 +03:00
{
2023-01-09 17:25:18 +02:00
if ( text . empty ( ) )
continue ;
2023-01-09 19:14:21 +02:00
auto result = CMessage : : breakText ( text , pos . w , FONT_SMALL ) ;
2023-01-09 17:25:18 +02:00
if ( result . size ( ) > 2 )
result . resize ( 2 ) ;
return result ;
2022-12-12 18:23:41 +02:00
}
2023-01-09 17:25:18 +02:00
// log is small enough to fit entirely - display it as such
if ( logEntries . size ( ) < 3 )
return logEntries ;
return { logEntries [ scrollPosition - 1 ] , logEntries [ scrollPosition ] } ;
}
std : : vector < std : : string > BattleConsole : : splitText ( const std : : string & text )
{
std : : vector < std : : string > lines ;
std : : vector < std : : string > output ;
boost : : split ( lines , text , boost : : is_any_of ( " \n " ) ) ;
for ( auto const & line : lines )
2022-12-12 18:23:41 +02:00
{
2023-01-09 17:25:18 +02:00
if ( graphics - > fonts [ FONT_SMALL ] - > getStringWidth ( text ) < pos . w )
2011-12-22 16:05:19 +03:00
{
2023-01-09 17:25:18 +02:00
output . push_back ( line ) ;
2011-12-22 16:05:19 +03:00
}
else
{
2023-01-09 17:25:18 +02:00
std : : vector < std : : string > substrings = CMessage : : breakText ( line , pos . w , FONT_SMALL ) ;
output . insert ( output . end ( ) , substrings . begin ( ) , substrings . end ( ) ) ;
2011-12-22 16:05:19 +03:00
}
}
2023-01-09 17:25:18 +02:00
return output ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
bool BattleConsole : : addText ( const std : : string & text )
2011-12-22 16:05:19 +03:00
{
2017-08-11 13:38:10 +02:00
logGlobal - > trace ( " CBattleConsole message: %s " , text ) ;
2011-12-22 16:05:19 +03:00
2023-01-09 17:25:18 +02:00
auto newLines = splitText ( text ) ;
logEntries . insert ( logEntries . end ( ) , newLines . begin ( ) , newLines . end ( ) ) ;
2022-12-12 18:23:41 +02:00
scrollPosition = ( int ) logEntries . size ( ) - 1 ;
2022-12-21 17:02:53 +02:00
redraw ( ) ;
2011-12-22 16:05:19 +03:00
return true ;
}
2022-12-09 13:26:17 +02:00
void BattleConsole : : scrollUp ( ui32 by )
2022-11-18 17:54:10 +02:00
{
2022-12-12 18:23:41 +02:00
if ( scrollPosition > static_cast < int > ( by ) )
scrollPosition - = by ;
2022-12-21 17:02:53 +02:00
redraw ( ) ;
2022-11-18 17:54:10 +02:00
}
2011-12-22 16:05:19 +03:00
2022-12-09 13:26:17 +02:00
void BattleConsole : : scrollDown ( ui32 by )
2012-02-20 11:19:03 +03:00
{
2022-12-12 18:23:41 +02:00
if ( scrollPosition + by < logEntries . size ( ) )
scrollPosition + = by ;
2022-12-21 17:02:53 +02:00
redraw ( ) ;
2012-02-20 11:19:03 +03:00
}
2022-12-21 17:02:53 +02:00
BattleConsole : : BattleConsole ( std : : shared_ptr < CPicture > backgroundSource , const Point & objectPos , const Point & imagePos , const Point & size )
2022-12-12 18:23:41 +02:00
: scrollPosition ( - 1 )
, enteringText ( false )
2011-12-22 16:05:19 +03:00
{
2022-12-21 17:02:53 +02:00
OBJ_CONSTRUCTION_CAPTURING_ALL_NO_DISPOSE ;
pos + = objectPos ;
pos . w = size . x ;
pos . h = size . y ;
background = std : : make_shared < CPicture > ( backgroundSource - > getSurface ( ) , Rect ( imagePos , size ) , 0 , 0 ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-19 22:06:01 +02:00
void BattleConsole : : deactivate ( )
2011-12-22 16:05:19 +03:00
{
2022-12-12 18:23:41 +02:00
if ( enteringText )
2022-12-19 22:53:31 +02:00
LOCPLINT - > cingconsole - > endEnteringText ( false ) ;
2022-12-19 22:06:01 +02:00
CIntObject : : deactivate ( ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-12 18:23:41 +02:00
void BattleConsole : : setEnteringMode ( bool on )
{
consoleText . clear ( ) ;
if ( on )
{
assert ( enteringText = = false ) ;
2023-01-17 22:01:35 +02:00
CSDL_Ext : : startTextInput ( pos ) ;
2022-12-12 18:23:41 +02:00
}
else
{
assert ( enteringText = = true ) ;
CSDL_Ext : : stopTextInput ( ) ;
}
enteringText = on ;
2023-01-05 13:05:16 +02:00
redraw ( ) ;
2022-12-12 18:23:41 +02:00
}
void BattleConsole : : setEnteredText ( const std : : string & text )
2011-12-22 16:05:19 +03:00
{
2022-12-12 18:23:41 +02:00
assert ( enteringText = = true ) ;
consoleText = text ;
2022-12-21 17:02:53 +02:00
redraw ( ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
void BattleConsole : : write ( const std : : string & Text )
2011-12-22 16:05:19 +03:00
{
2022-12-12 18:23:41 +02:00
hoverText = Text ;
2022-12-21 17:02:53 +02:00
redraw ( ) ;
2022-12-12 18:23:41 +02:00
}
void BattleConsole : : clearIfMatching ( const std : : string & Text )
{
if ( hoverText = = Text )
clear ( ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-12 18:23:41 +02:00
void BattleConsole : : clear ( )
2022-11-18 17:54:10 +02:00
{
2022-12-12 18:23:41 +02:00
write ( { } ) ;
2022-11-18 17:54:10 +02:00
}
2012-09-27 20:16:41 +03:00
2022-12-21 17:02:53 +02:00
const CGHeroInstance * BattleHero : : instance ( )
{
return hero ;
}
2022-12-11 22:09:57 +02:00
void BattleHero : : render ( Canvas & canvas )
2011-12-22 16:05:19 +03:00
{
2022-12-12 23:31:18 +02:00
size_t groupIndex = static_cast < size_t > ( phase ) ;
2017-09-05 15:44:27 +02:00
2022-12-12 23:31:18 +02:00
auto flagFrame = flagAnimation - > getImage ( flagCurrentFrame , 0 , true ) ;
auto heroFrame = animation - > getImage ( currentFrame , groupIndex , true ) ;
2017-09-05 15:44:27 +02:00
2023-01-05 14:16:01 +02:00
Point heroPosition = pos . center ( ) - parent - > pos . topLeft ( ) - heroFrame - > dimensions ( ) / 2 ;
Point flagPosition = pos . center ( ) - parent - > pos . topLeft ( ) - flagFrame - > dimensions ( ) / 2 ;
2012-08-29 17:55:31 +03:00
2022-12-21 01:08:56 +02:00
if ( defender )
2022-12-12 23:31:18 +02:00
flagPosition + = Point ( - 4 , - 41 ) ;
2011-12-22 16:05:19 +03:00
else
2022-12-12 23:31:18 +02:00
flagPosition + = Point ( 4 , - 41 ) ;
2017-09-05 15:44:27 +02:00
2022-12-12 23:31:18 +02:00
canvas . draw ( flagFrame , flagPosition ) ;
canvas . draw ( heroFrame , heroPosition ) ;
2012-08-29 17:55:31 +03:00
2023-01-31 00:42:50 +02:00
float timePassed = float ( GH . mainFPSmng - > getElapsedMilliseconds ( ) ) / 1000.f ;
flagCurrentFrame + = currentSpeed * timePassed ;
currentFrame + = currentSpeed * timePassed ;
2017-09-05 15:44:27 +02:00
2022-12-12 23:31:18 +02:00
if ( flagCurrentFrame > = flagAnimation - > size ( 0 ) )
flagCurrentFrame - = flagAnimation - > size ( 0 ) ;
2017-09-05 15:44:27 +02:00
2022-12-12 23:31:18 +02:00
if ( currentFrame > = animation - > size ( groupIndex ) )
2011-12-22 16:05:19 +03:00
{
2022-12-12 23:31:18 +02:00
currentFrame - = animation - > size ( groupIndex ) ;
2022-12-13 18:49:35 +02:00
switchToNextPhase ( ) ;
2011-12-22 16:05:19 +03:00
}
}
2022-12-13 18:49:35 +02:00
void BattleHero : : pause ( )
{
currentSpeed = 0.f ;
}
void BattleHero : : play ( )
{
2023-01-31 00:42:50 +02:00
//H3 speed: 10 fps ( 100 ms per frame)
currentSpeed = 10.f ;
2022-12-13 18:49:35 +02:00
}
2022-12-12 23:31:18 +02:00
float BattleHero : : getFrame ( ) const
{
return currentFrame ;
}
2022-12-21 17:02:53 +02:00
void BattleHero : : collectRenderableObjects ( BattleRenderer & renderer )
{
auto hex = defender ? BattleHex ( GameConstants : : BFIELD_WIDTH - 1 ) : BattleHex ( 0 ) ;
renderer . insert ( EBattleFieldLayer : : HEROES , hex , [ this ] ( BattleRenderer : : RendererRef canvas )
{
render ( canvas ) ;
} ) ;
}
2022-12-12 23:31:18 +02:00
void BattleHero : : onPhaseFinished ( const std : : function < void ( ) > & callback )
{
phaseFinishedCallback = callback ;
}
void BattleHero : : setPhase ( EHeroAnimType newPhase )
2011-12-22 16:05:19 +03:00
{
2012-08-29 17:55:31 +03:00
nextPhase = newPhase ;
switchToNextPhase ( ) ; //immediately switch to next phase and then restore idling phase
2022-12-12 23:31:18 +02:00
nextPhase = EHeroAnimType : : HOLDING ;
2011-12-22 16:05:19 +03:00
}
2023-01-29 17:52:19 +02:00
void BattleHero : : heroLeftClicked ( )
2011-12-22 16:05:19 +03:00
{
2022-12-12 23:31:18 +02:00
if ( owner . actionsController - > spellcastingModeActive ( ) ) //we are casting a spell
2011-12-22 16:05:19 +03:00
return ;
2023-01-29 17:52:19 +02:00
if ( ! hero | | ! owner . makingTurn ( ) )
2017-09-05 15:44:27 +02:00
return ;
2022-12-21 01:08:56 +02:00
if ( owner . getCurrentPlayerInterface ( ) - > cb - > battleCanCastSpell ( hero , spells : : Mode : : HERO ) = = ESpellCastProblem : : OK ) //check conditions
2011-12-22 16:05:19 +03:00
{
2022-12-12 23:31:18 +02:00
BattleHex hoveredHex = owner . fieldController - > getHoveredHex ( ) ;
2022-11-17 23:57:51 +02:00
//do nothing when any hex is hovered - hero's animation overlaps battlefield
if ( hoveredHex ! = BattleHex : : INVALID )
return ;
2022-12-18 22:32:07 +02:00
CCS - > curh - > set ( Cursor : : Map : : POINTER ) ;
2011-12-22 16:05:19 +03:00
2022-12-21 01:08:56 +02:00
GH . pushIntT < CSpellWindow > ( hero , owner . getCurrentPlayerInterface ( ) ) ;
2011-12-22 16:05:19 +03:00
}
}
2023-01-29 17:52:19 +02:00
void BattleHero : : heroRightClicked ( )
2016-09-27 14:13:20 +02:00
{
Point windowPosition ;
2023-01-17 22:18:34 +02:00
windowPosition . x = ( ! defender ) ? owner . fieldController - > pos . left ( ) + 1 : owner . fieldController - > pos . right ( ) - 79 ;
2022-12-21 17:02:53 +02:00
windowPosition . y = owner . fieldController - > pos . y + 135 ;
2016-09-27 14:13:20 +02:00
InfoAboutHero targetHero ;
2023-01-29 17:52:19 +02:00
if ( owner . makingTurn ( ) | | settings [ " session " ] [ " spectate " ] . Bool ( ) )
2016-09-27 14:13:20 +02:00
{
2022-12-21 01:08:56 +02:00
auto h = defender ? owner . defendingHeroInstance : owner . attackingHeroInstance ;
2017-06-03 03:28:03 +02:00
targetHero . initFromHero ( h , InfoAboutHero : : EInfoLevel : : INBATTLE ) ;
2022-12-09 13:26:17 +02:00
GH . pushIntT < HeroInfoWindow > ( targetHero , & windowPosition ) ;
2016-09-27 14:13:20 +02:00
}
}
2022-12-09 13:26:17 +02:00
void BattleHero : : switchToNextPhase ( )
2012-08-29 17:55:31 +03:00
{
2022-12-12 23:31:18 +02:00
phase = nextPhase ;
currentFrame = 0.f ;
2022-12-13 18:49:35 +02:00
auto copy = phaseFinishedCallback ;
phaseFinishedCallback . clear ( ) ;
copy ( ) ;
2012-08-29 17:55:31 +03:00
}
2022-12-21 01:08:56 +02:00
BattleHero : : BattleHero ( const BattleInterface & owner , const CGHeroInstance * hero , bool defender ) :
defender ( defender ) ,
hero ( hero ) ,
2022-12-12 23:31:18 +02:00
owner ( owner ) ,
phase ( EHeroAnimType : : HOLDING ) ,
nextPhase ( EHeroAnimType : : HOLDING ) ,
2022-12-13 18:49:35 +02:00
currentSpeed ( 0.f ) ,
2022-12-12 23:31:18 +02:00
currentFrame ( 0.f ) ,
flagCurrentFrame ( 0.f )
2011-12-22 16:05:19 +03:00
{
2022-12-21 01:08:56 +02:00
std : : string animationPath ;
if ( ! hero - > type - > battleImage . empty ( ) )
animationPath = hero - > type - > battleImage ;
else
if ( hero - > sex )
animationPath = hero - > type - > heroClass - > imageBattleFemale ;
else
animationPath = hero - > type - > heroClass - > imageBattleMale ;
2017-09-05 15:44:27 +02:00
animation = std : : make_shared < CAnimation > ( animationPath ) ;
animation - > preload ( ) ;
2022-12-12 23:31:18 +02:00
pos . w = 64 ;
pos . h = 136 ;
2022-12-21 17:02:53 +02:00
pos . x = owner . fieldController - > pos . x + ( defender ? ( owner . fieldController - > pos . w - pos . w ) : 0 ) ;
pos . y = owner . fieldController - > pos . y ;
2022-12-12 23:31:18 +02:00
2022-12-21 01:08:56 +02:00
if ( defender )
2017-09-05 15:44:27 +02:00
animation - > verticalFlip ( ) ;
2011-12-22 16:05:19 +03:00
2022-12-21 01:08:56 +02:00
if ( defender )
2017-09-05 15:44:27 +02:00
flagAnimation = std : : make_shared < CAnimation > ( " CMFLAGR " ) ;
2011-12-22 16:05:19 +03:00
else
2017-09-05 15:44:27 +02:00
flagAnimation = std : : make_shared < CAnimation > ( " CMFLAGL " ) ;
flagAnimation - > preload ( ) ;
2022-12-21 01:08:56 +02:00
flagAnimation - > playerColored ( hero - > tempOwner ) ;
2011-12-22 16:05:19 +03:00
2012-08-29 17:55:31 +03:00
switchToNextPhase ( ) ;
2022-12-13 18:49:35 +02:00
play ( ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
HeroInfoWindow : : HeroInfoWindow ( const InfoAboutHero & hero , Point * position )
2018-04-07 13:34:11 +02:00
: CWindowObject ( RCLICK_POPUP | SHADOW_DISABLED , " CHRPOP " )
{
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
if ( position ! = nullptr )
moveTo ( * position ) ;
background - > colorize ( hero . owner ) ; //maybe add this functionality to base class?
auto attack = hero . details - > primskills [ 0 ] ;
auto defense = hero . details - > primskills [ 1 ] ;
auto power = hero . details - > primskills [ 2 ] ;
auto knowledge = hero . details - > primskills [ 3 ] ;
auto morale = hero . details - > morale ;
auto luck = hero . details - > luck ;
auto currentSpellPoints = hero . details - > mana ;
auto maxSpellPoints = hero . details - > manaLimit ;
icons . push_back ( std : : make_shared < CAnimImage > ( " PortraitsLarge " , hero . portrait , 0 , 10 , 6 ) ) ;
//primary stats
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 9 , 75 , EFonts : : FONT_TINY , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 380 ] + " : " ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 9 , 87 , EFonts : : FONT_TINY , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 381 ] + " : " ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 9 , 99 , EFonts : : FONT_TINY , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 382 ] + " : " ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 9 , 111 , EFonts : : FONT_TINY , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 383 ] + " : " ) ) ;
2018-04-07 13:34:11 +02:00
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 69 , 87 , EFonts : : FONT_TINY , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE , std : : to_string ( attack ) ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 69 , 99 , EFonts : : FONT_TINY , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE , std : : to_string ( defense ) ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 69 , 111 , EFonts : : FONT_TINY , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE , std : : to_string ( power ) ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 69 , 123 , EFonts : : FONT_TINY , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE , std : : to_string ( knowledge ) ) ) ;
2018-04-07 13:34:11 +02:00
//morale+luck
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 9 , 131 , EFonts : : FONT_TINY , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 384 ] + " : " ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 9 , 143 , EFonts : : FONT_TINY , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 385 ] + " : " ) ) ;
2018-04-07 13:34:11 +02:00
icons . push_back ( std : : make_shared < CAnimImage > ( " IMRL22 " , morale + 3 , 0 , 47 , 131 ) ) ;
icons . push_back ( std : : make_shared < CAnimImage > ( " ILCK22 " , luck + 3 , 0 , 47 , 143 ) ) ;
//spell points
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 39 , 174 , EFonts : : FONT_TINY , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 387 ] ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 39 , 186 , EFonts : : FONT_TINY , ETextAlignment : : CENTER , Colors : : WHITE , std : : to_string ( currentSpellPoints ) + " / " + std : : to_string ( maxSpellPoints ) ) ) ;
2018-04-07 13:34:11 +02:00
}
2022-12-13 13:58:16 +02:00
BattleOptionsWindow : : BattleOptionsWindow ( BattleInterface & owner ) :
2022-11-27 02:26:02 +02:00
CWindowObject ( PLAYER_COLORED , " comopbck.bmp " )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2011-12-22 16:05:19 +03:00
2022-12-13 13:58:16 +02:00
auto viewGrid = std : : make_shared < CToggleButton > ( Point ( 25 , 56 ) , " sysopchk.def " , CGI - > generaltexth - > zelp [ 427 ] , [ & ] ( bool on ) { owner . setPrintCellBorders ( on ) ; } ) ;
2014-08-03 14:16:19 +03:00
viewGrid - > setSelected ( settings [ " battle " ] [ " cellBorders " ] . Bool ( ) ) ;
2018-04-07 13:34:11 +02:00
toggles . push_back ( viewGrid ) ;
2022-12-13 13:58:16 +02:00
auto movementShadow = std : : make_shared < CToggleButton > ( Point ( 25 , 89 ) , " sysopchk.def " , CGI - > generaltexth - > zelp [ 428 ] , [ & ] ( bool on ) { owner . setPrintStackRange ( on ) ; } ) ;
2014-08-03 14:16:19 +03:00
movementShadow - > setSelected ( settings [ " battle " ] [ " stackRange " ] . Bool ( ) ) ;
2018-04-07 13:34:11 +02:00
toggles . push_back ( movementShadow ) ;
2022-12-13 13:58:16 +02:00
auto mouseShadow = std : : make_shared < CToggleButton > ( Point ( 25 , 122 ) , " sysopchk.def " , CGI - > generaltexth - > zelp [ 429 ] , [ & ] ( bool on ) { owner . setPrintMouseShadow ( on ) ; } ) ;
2014-08-03 14:16:19 +03:00
mouseShadow - > setSelected ( settings [ " battle " ] [ " mouseShadow " ] . Bool ( ) ) ;
2018-04-07 13:34:11 +02:00
toggles . push_back ( mouseShadow ) ;
2022-12-13 13:58:16 +02:00
animSpeeds = std : : make_shared < CToggleGroup > ( [ & ] ( int value ) { owner . setAnimSpeed ( value ) ; } ) ;
2018-04-07 13:34:11 +02:00
std : : shared_ptr < CToggleButton > toggle ;
toggle = std : : make_shared < CToggleButton > ( Point ( 28 , 225 ) , " sysopb9.def " , CGI - > generaltexth - > zelp [ 422 ] ) ;
2023-01-27 23:16:02 +02:00
animSpeeds - > addToggle ( 1 , toggle ) ;
2018-04-07 13:34:11 +02:00
toggle = std : : make_shared < CToggleButton > ( Point ( 92 , 225 ) , " sysob10.def " , CGI - > generaltexth - > zelp [ 423 ] ) ;
2023-01-27 23:16:02 +02:00
animSpeeds - > addToggle ( 2 , toggle ) ;
2018-04-07 13:34:11 +02:00
toggle = std : : make_shared < CToggleButton > ( Point ( 156 , 225 ) , " sysob11.def " , CGI - > generaltexth - > zelp [ 424 ] ) ;
2023-01-27 23:16:02 +02:00
animSpeeds - > addToggle ( 3 , toggle ) ;
2014-08-03 14:16:19 +03:00
2022-12-13 13:58:16 +02:00
animSpeeds - > setSelected ( owner . getAnimSpeed ( ) ) ;
2014-08-03 14:16:19 +03:00
2018-04-07 13:34:11 +02:00
setToDefault = std : : make_shared < CButton > ( Point ( 246 , 359 ) , " codefaul.def " , CGI - > generaltexth - > zelp [ 393 ] , [ & ] ( ) { bDefaultf ( ) ; } ) ;
2014-08-03 14:16:19 +03:00
setToDefault - > setImageOrder ( 1 , 0 , 2 , 3 ) ;
2018-04-07 13:34:11 +02:00
exit = std : : make_shared < CButton > ( Point ( 357 , 359 ) , " soretrn.def " , CGI - > generaltexth - > zelp [ 392 ] , [ & ] ( ) { bExitf ( ) ; } , SDLK_RETURN ) ;
2014-08-03 14:16:19 +03:00
exit - > setImageOrder ( 1 , 0 , 2 , 3 ) ;
2011-12-22 16:05:19 +03:00
//creating labels
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 242 , 32 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 392 ] ) ) ; //window title
labels . push_back ( std : : make_shared < CLabel > ( 122 , 214 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 393 ] ) ) ; //animation speed
labels . push_back ( std : : make_shared < CLabel > ( 122 , 293 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 394 ] ) ) ; //music volume
labels . push_back ( std : : make_shared < CLabel > ( 122 , 359 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 395 ] ) ) ; //effects' volume
labels . push_back ( std : : make_shared < CLabel > ( 353 , 66 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 396 ] ) ) ; //auto - combat options
labels . push_back ( std : : make_shared < CLabel > ( 353 , 265 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 397 ] ) ) ; //creature info
2011-12-22 16:05:19 +03:00
//auto - combat options
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 283 , 86 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 398 ] ) ) ; //creatures
labels . push_back ( std : : make_shared < CLabel > ( 283 , 116 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 399 ] ) ) ; //spells
labels . push_back ( std : : make_shared < CLabel > ( 283 , 146 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 400 ] ) ) ; //catapult
labels . push_back ( std : : make_shared < CLabel > ( 283 , 176 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 151 ] ) ) ; //ballista
labels . push_back ( std : : make_shared < CLabel > ( 283 , 206 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 401 ] ) ) ; //first aid tent
2011-12-22 16:05:19 +03:00
//creature info
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 283 , 285 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 402 ] ) ) ; //all stats
labels . push_back ( std : : make_shared < CLabel > ( 283 , 315 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 403 ] ) ) ; //spells only
2011-12-22 16:05:19 +03:00
//general options
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 61 , 57 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 404 ] ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 61 , 90 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 405 ] ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 61 , 123 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 406 ] ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 61 , 156 , FONT_MEDIUM , ETextAlignment : : TOPLEFT , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 407 ] ) ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
void BattleOptionsWindow : : bDefaultf ( )
2011-12-22 16:05:19 +03:00
{
2014-08-03 14:16:19 +03:00
//TODO: implement
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
void BattleOptionsWindow : : bExitf ( )
2011-12-22 16:05:19 +03:00
{
2018-07-25 00:36:48 +02:00
close ( ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
BattleResultWindow : : BattleResultWindow ( const BattleResult & br , CPlayerInterface & _owner )
2018-04-07 13:34:11 +02:00
: owner ( _owner )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2023-01-17 22:01:35 +02:00
pos = CSDL_Ext : : genRect ( 561 , 470 , ( screen - > w - 800 ) / 2 + 165 , ( screen - > h - 600 ) / 2 + 19 ) ;
2018-04-07 13:34:11 +02:00
background = std : : make_shared < CPicture > ( " CPRESULT " ) ;
background - > colorize ( owner . playerID ) ;
2012-05-13 18:04:21 +03:00
2018-04-07 13:34:11 +02:00
exit = std : : make_shared < CButton > ( Point ( 384 , 505 ) , " iok6432.def " , std : : make_pair ( " " , " " ) , [ & ] ( ) { bExitf ( ) ; } , SDLK_RETURN ) ;
2018-03-17 06:23:22 +02:00
exit - > setBorderColor ( Colors : : METALLIC_GOLD ) ;
2011-12-22 16:05:19 +03:00
2022-04-16 12:18:41 +02:00
if ( br . winner = = 0 ) //attacker won
2011-12-22 16:05:19 +03:00
{
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 59 , 124 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 410 ] ) ) ;
2011-12-22 16:05:19 +03:00
}
2022-04-16 12:18:41 +02:00
else
2011-12-22 16:05:19 +03:00
{
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 59 , 124 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 411 ] ) ) ;
2022-04-16 12:18:41 +02:00
}
if ( br . winner = = 1 )
{
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 412 , 124 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 410 ] ) ) ;
2011-12-22 16:05:19 +03:00
}
2022-04-16 12:18:41 +02:00
else
{
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 408 , 124 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 411 ] ) ) ;
2022-04-16 12:18:41 +02:00
}
2011-12-22 16:05:19 +03:00
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 232 , 302 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 407 ] ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 232 , 332 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 408 ] ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 232 , 428 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 409 ] ) ) ;
2011-12-22 16:05:19 +03:00
2013-06-23 14:25:48 +03:00
std : : string sideNames [ 2 ] = { " N/A " , " N/A " } ;
2011-12-22 16:05:19 +03:00
2013-06-23 14:25:48 +03:00
for ( int i = 0 ; i < 2 ; i + + )
2011-12-22 16:05:19 +03:00
{
2013-06-23 14:25:48 +03:00
auto heroInfo = owner . cb - > battleGetHeroInfo ( i ) ;
const int xs [ ] = { 21 , 392 } ;
2016-10-16 08:27:22 +02:00
if ( heroInfo . portrait > = 0 ) //attacking hero
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
icons . push_back ( std : : make_shared < CAnimImage > ( " PortraitsLarge " , heroInfo . portrait , 0 , xs [ i ] , 38 ) ) ;
2013-06-23 14:25:48 +03:00
sideNames [ i ] = heroInfo . name ;
2011-12-22 16:05:19 +03:00
}
2013-06-23 14:25:48 +03:00
else
2011-12-22 16:05:19 +03:00
{
2013-06-23 14:25:48 +03:00
auto stacks = owner . cb - > battleGetAllStacks ( ) ;
2018-04-07 13:34:11 +02:00
vstd : : erase_if ( stacks , [ i ] ( const CStack * stack ) //erase stack of other side and not coming from garrison
{
return stack - > side ! = i | | ! stack - > base ;
} ) ;
auto best = vstd : : maxElementByFun ( stacks , [ ] ( const CStack * stack )
{
return stack - > type - > AIValue ;
} ) ;
2013-06-23 14:25:48 +03:00
if ( best ! = stacks . end ( ) ) //should be always but to be safe...
2011-12-22 16:05:19 +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
icons . push_back ( std : : make_shared < CAnimImage > ( " TWCRPORT " , ( * best ) - > type - > getIconIndex ( ) , 0 , xs [ i ] , 38 ) ) ;
2023-01-02 18:00:51 +02:00
sideNames [ i ] = ( * best ) - > type - > getNamePluralTranslated ( ) ;
2011-12-22 16:05:19 +03:00
}
}
}
//printing attacker and defender's names
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 89 , 37 , FONT_SMALL , ETextAlignment : : TOPLEFT , Colors : : WHITE , sideNames [ 0 ] ) ) ;
labels . push_back ( std : : make_shared < CLabel > ( 381 , 53 , FONT_SMALL , ETextAlignment : : BOTTOMRIGHT , Colors : : WHITE , sideNames [ 1 ] ) ) ;
2012-05-13 18:04:21 +03:00
2013-06-23 14:25:48 +03:00
//printing casualties
2011-12-22 16:05:19 +03:00
for ( int step = 0 ; step < 2 ; + + step )
{
if ( br . casualties [ step ] . size ( ) = = 0 )
{
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 235 , 360 + 97 * step , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 523 ] ) ) ;
2011-12-22 16:05:19 +03:00
}
else
{
2020-10-01 10:38:06 +02:00
int xPos = 235 - ( ( int ) br . casualties [ step ] . size ( ) * 32 + ( ( int ) br . casualties [ step ] . size ( ) - 1 ) * 10 ) / 2 ; //increment by 42 with each picture
2018-04-07 13:34:11 +02:00
int yPos = 344 + step * 97 ;
2013-06-29 16:05:48 +03:00
for ( auto & elem : br . casualties [ step ] )
2011-12-22 16:05:19 +03:00
{
2022-12-07 15:57:17 +02:00
auto creature = CGI - > creatures ( ) - > getByIndex ( elem . first ) ;
if ( creature - > getId ( ) = = CreatureID : : ARROW_TOWERS )
continue ; // do not show destroyed towers in battle results
icons . push_back ( std : : make_shared < CAnimImage > ( " CPRSMALL " , creature - > getIconIndex ( ) , 0 , xPos , yPos ) ) ;
2011-12-22 16:05:19 +03:00
std : : ostringstream amount ;
2013-06-29 16:05:48 +03:00
amount < < elem . second ;
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( xPos + 16 , yPos + 42 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , amount . str ( ) ) ) ;
2011-12-22 16:05:19 +03:00
xPos + = 42 ;
}
}
}
//printing result description
2013-06-23 14:25:48 +03:00
bool weAreAttacker = ! ( owner . cb - > battleGetMySide ( ) ) ;
2011-12-22 16:05:19 +03:00
if ( ( br . winner = = 0 & & weAreAttacker ) | | ( br . winner = = 1 & & ! weAreAttacker ) ) //we've won
{
2018-04-07 13:34:11 +02:00
int text = 304 ;
2011-12-22 16:05:19 +03:00
switch ( br . result )
{
2018-04-07 13:34:11 +02:00
case BattleResult : : NORMAL :
break ;
case BattleResult : : ESCAPE :
text = 303 ;
break ;
case BattleResult : : SURRENDER :
text = 302 ;
break ;
default :
logGlobal - > error ( " Invalid battle result code %d. Assumed normal. " , static_cast < int > ( br . result ) ) ;
break ;
2011-12-22 16:05:19 +03:00
}
2022-11-13 14:24:15 +02:00
CCS - > musich - > playMusic ( " Music/Win Battle " , false , true ) ;
2012-08-21 20:37:06 +03:00
CCS - > videoh - > open ( " WIN3.BIK " ) ;
2011-12-22 16:05:19 +03:00
std : : string str = CGI - > generaltexth - > allTexts [ text ] ;
2013-06-23 14:25:48 +03:00
const CGHeroInstance * ourHero = owner . cb - > battleGetMyHero ( ) ;
2011-12-22 16:05:19 +03:00
if ( ourHero )
{
str + = CGI - > generaltexth - > allTexts [ 305 ] ;
2023-01-02 13:27:03 +02:00
boost : : algorithm : : replace_first ( str , " %s " , ourHero - > getNameTranslated ( ) ) ;
2018-04-07 13:34:11 +02:00
boost : : algorithm : : replace_first ( str , " %d " , boost : : lexical_cast < std : : string > ( br . exp [ weAreAttacker ? 0 : 1 ] ) ) ;
2011-12-22 16:05:19 +03:00
}
2016-10-16 08:27:22 +02:00
2022-11-26 23:12:20 +02:00
description = std : : make_shared < CTextBox > ( str , Rect ( 69 , 203 , 330 , 68 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2011-12-22 16:05:19 +03:00
}
else // we lose
{
2018-04-07 13:34:11 +02:00
int text = 311 ;
std : : string musicName = " Music/LoseCombat " ;
std : : string videoName = " LBSTART.BIK " ;
2011-12-22 16:05:19 +03:00
switch ( br . result )
{
2013-02-23 00:03:56 +03:00
case BattleResult : : NORMAL :
2018-04-07 13:34:11 +02:00
break ;
case BattleResult : : ESCAPE :
musicName = " Music/Retreat Battle " ;
videoName = " RTSTART.BIK " ;
text = 310 ;
break ;
2013-02-23 00:03:56 +03:00
case BattleResult : : SURRENDER :
2018-04-07 13:34:11 +02:00
musicName = " Music/Surrender Battle " ;
videoName = " SURRENDER.BIK " ;
text = 309 ;
break ;
default :
logGlobal - > error ( " Invalid battle result code %d. Assumed normal. " , static_cast < int > ( br . result ) ) ;
break ;
2011-12-22 16:05:19 +03:00
}
2022-11-13 14:24:15 +02:00
CCS - > musich - > playMusic ( musicName , false , true ) ;
2018-04-07 13:34:11 +02:00
CCS - > videoh - > open ( videoName ) ;
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 235 , 235 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ text ] ) ) ;
2011-12-22 16:05:19 +03:00
}
}
2022-12-09 13:26:17 +02:00
void BattleResultWindow : : activate ( )
2011-12-22 16:05:19 +03:00
{
2013-06-23 14:25:48 +03:00
owner . showingDialog - > set ( true ) ;
2012-05-26 13:02:55 +03:00
CIntObject : : activate ( ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
void BattleResultWindow : : show ( SDL_Surface * to )
2011-12-22 16:05:19 +03:00
{
2012-05-13 18:04:21 +03:00
CIntObject : : show ( to ) ;
2012-05-26 13:02:55 +03:00
CCS - > videoh - > update ( pos . x + 107 , pos . y + 70 , screen , true , false ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
void BattleResultWindow : : bExitf ( )
2011-12-22 16:05:19 +03:00
{
2013-06-23 14:25:48 +03:00
CPlayerInterface & intTmp = owner ; //copy reference because "this" will be destructed soon
2018-07-25 00:36:48 +02:00
close ( ) ;
2022-12-21 18:04:19 +02:00
if ( dynamic_cast < BattleWindow * > ( GH . topInt ( ) . get ( ) ) )
2013-06-23 14:25:48 +03:00
GH . popInts ( 1 ) ; //pop battle interface if present
2016-10-16 08:27:22 +02:00
//Result window and battle interface are gone. We requested all dialogs to be closed before opening the battle,
2013-06-23 14:25:48 +03:00
//so we can be sure that there is no dialogs left on GUI stack.
intTmp . showingDialog - > setn ( false ) ;
2011-12-22 16:05:19 +03:00
CCS - > videoh - > close ( ) ;
}
2022-12-13 13:58:16 +02:00
StackQueue : : StackQueue ( bool Embedded , BattleInterface & owner )
2017-07-20 06:08:49 +02:00
: embedded ( Embedded ) ,
2022-12-13 13:58:16 +02:00
owner ( owner )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2011-12-22 16:05:19 +03:00
if ( embedded )
{
2022-12-21 17:02:53 +02:00
pos . w = QUEUE_SIZE * 41 ;
pos . h = 49 ;
pos . x + = parent - > pos . w / 2 - pos . w / 2 ;
pos . y + = 10 ;
2017-07-20 06:08:49 +02:00
icons = std : : make_shared < CAnimation > ( " CPRSMALL " ) ;
stateIcons = std : : make_shared < CAnimation > ( " VCMI/BATTLEQUEUE/STATESSMALL " ) ;
2011-12-22 16:05:19 +03:00
}
else
{
2012-08-28 19:28:21 +03:00
pos . w = 800 ;
pos . h = 85 ;
2022-12-21 17:02:53 +02:00
pos . x + = 0 ;
pos . y - = pos . h ;
2017-07-20 06:08:49 +02:00
2018-04-07 13:34:11 +02:00
background = std : : make_shared < CFilledTexture > ( " DIBOXBCK " , Rect ( 0 , 0 , pos . w , pos . h ) ) ;
2017-07-20 06:08:49 +02:00
icons = std : : make_shared < CAnimation > ( " TWCRPORT " ) ;
stateIcons = std : : make_shared < CAnimation > ( " VCMI/BATTLEQUEUE/STATESSMALL " ) ;
//TODO: where use big icons?
//stateIcons = std::make_shared<CAnimation>("VCMI/BATTLEQUEUE/STATESBIG");
2011-12-22 16:05:19 +03:00
}
2017-07-20 06:08:49 +02:00
stateIcons - > preload ( ) ;
2011-12-22 16:05:19 +03:00
stackBoxes . resize ( QUEUE_SIZE ) ;
2012-08-28 19:28:21 +03:00
for ( int i = 0 ; i < stackBoxes . size ( ) ; i + + )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
stackBoxes [ i ] = std : : make_shared < StackBox > ( this ) ;
2022-12-21 17:02:53 +02:00
stackBoxes [ i ] - > moveBy ( Point ( 1 + ( embedded ? 41 : 80 ) * i , 0 ) ) ;
2011-12-22 16:05:19 +03:00
}
}
2023-01-05 12:57:34 +02:00
void StackQueue : : show ( SDL_Surface * to )
{
if ( embedded )
showAll ( to ) ;
CIntObject : : show ( to ) ;
}
2022-12-09 13:26:17 +02:00
void StackQueue : : update ( )
2011-12-22 16:05:19 +03:00
{
2017-07-20 06:08:49 +02:00
std : : vector < battle : : Units > queueData ;
2011-12-22 16:05:19 +03:00
2022-12-13 13:58:16 +02:00
owner . getCurrentPlayerInterface ( ) - > cb - > battleGetTurnOrder ( queueData , stackBoxes . size ( ) , 0 ) ;
2011-12-22 16:05:19 +03:00
2017-07-20 06:08:49 +02:00
size_t boxIndex = 0 ;
for ( size_t turn = 0 ; turn < queueData . size ( ) & & boxIndex < stackBoxes . size ( ) ; turn + + )
2011-12-22 16:05:19 +03:00
{
2017-07-20 06:08:49 +02:00
for ( size_t unitIndex = 0 ; unitIndex < queueData [ turn ] . size ( ) & & boxIndex < stackBoxes . size ( ) ; boxIndex + + , unitIndex + + )
2018-04-07 13:34:11 +02:00
stackBoxes [ boxIndex ] - > setUnit ( queueData [ turn ] [ unitIndex ] , turn ) ;
2011-12-22 16:05:19 +03:00
}
2017-07-20 06:08:49 +02:00
for ( ; boxIndex < stackBoxes . size ( ) ; boxIndex + + )
2018-04-07 13:34:11 +02:00
stackBoxes [ boxIndex ] - > setUnit ( nullptr ) ;
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
int32_t StackQueue : : getSiegeShooterIconID ( )
2022-11-29 14:59:50 +02:00
{
2023-01-04 15:17:50 +02:00
return owner . siegeController - > getSiegedTown ( ) - > town - > faction - > getIndex ( ) ;
2022-11-29 14:59:50 +02:00
}
2022-12-09 13:26:17 +02:00
StackQueue : : StackBox : : StackBox ( StackQueue * owner ) :
2022-11-29 14:59:50 +02:00
owner ( owner )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
background = std : : make_shared < CPicture > ( owner - > embedded ? " StackQueueSmall " : " StackQueueLarge " ) ;
2017-07-20 06:08:49 +02:00
2018-04-07 13:34:11 +02:00
pos . w = background - > pos . w ;
pos . h = background - > pos . h ;
2012-08-28 19:28:21 +03:00
2017-07-20 06:08:49 +02:00
if ( owner - > embedded )
{
2018-04-07 13:34:11 +02:00
icon = std : : make_shared < CAnimImage > ( owner - > icons , 0 , 0 , 5 , 2 ) ;
2022-11-26 23:12:20 +02:00
amount = std : : make_shared < CLabel > ( pos . w / 2 , pos . h - 7 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2017-07-20 06:08:49 +02:00
}
2011-12-22 16:05:19 +03:00
else
2017-07-20 06:08:49 +02:00
{
2018-04-07 13:34:11 +02:00
icon = std : : make_shared < CAnimImage > ( owner - > icons , 0 , 0 , 9 , 1 ) ;
2022-11-26 23:12:20 +02:00
amount = std : : make_shared < CLabel > ( pos . w / 2 , pos . h - 8 , FONT_MEDIUM , ETextAlignment : : CENTER , Colors : : WHITE ) ;
2011-12-22 16:05:19 +03:00
2017-07-20 06:08:49 +02:00
int icon_x = pos . w - 17 ;
int icon_y = pos . h - 18 ;
2018-04-07 13:34:11 +02:00
stateIcon = std : : make_shared < CAnimImage > ( owner - > stateIcons , 0 , 0 , icon_x , icon_y ) ;
2017-07-20 06:08:49 +02:00
stateIcon - > visible = false ;
}
2011-12-22 16:05:19 +03:00
}
2022-12-09 13:26:17 +02:00
void StackQueue : : StackBox : : setUnit ( const battle : : Unit * unit , size_t turn )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
if ( unit )
2011-12-22 16:05:19 +03:00
{
2018-04-07 13:34:11 +02:00
background - > colorize ( unit - > unitOwner ( ) ) ;
2017-07-20 06:08:49 +02:00
icon - > visible = true ;
2022-11-29 14:59:50 +02:00
// temporary code for mod compatibility:
// first, set icon that should definitely exist (arrow tower icon in base vcmi mod)
// second, try to switch to icon that should be provided by mod
// if mod is not up to date and does have arrow tower icon yet - second setFrame call will fail and retain previously set image
// for 1.2 release & later next line should be moved into 'else' block
icon - > setFrame ( unit - > creatureIconIndex ( ) , 0 ) ;
if ( unit - > unitType ( ) - > idNumber = = CreatureID : : ARROW_TOWERS )
icon - > setFrame ( owner - > getSiegeShooterIconID ( ) , 1 ) ;
2023-01-20 19:38:54 +02:00
amount - > setText ( CSDL_Ext : : makeNumberShort ( unit - > getCount ( ) , 4 ) ) ;
2017-07-20 06:08:49 +02:00
if ( stateIcon )
{
2020-10-01 10:38:06 +02:00
if ( unit - > defended ( ( int ) turn ) | | ( turn > 0 & & unit - > defended ( ( int ) turn - 1 ) ) )
2017-07-20 06:08:49 +02:00
{
stateIcon - > setFrame ( 0 , 0 ) ;
stateIcon - > visible = true ;
}
2020-10-01 10:38:06 +02:00
else if ( unit - > waited ( ( int ) turn ) )
2017-07-20 06:08:49 +02:00
{
stateIcon - > setFrame ( 1 , 0 ) ;
stateIcon - > visible = true ;
}
else
{
stateIcon - > visible = false ;
}
}
2011-12-22 16:05:19 +03:00
}
else
2017-07-20 06:08:49 +02:00
{
2018-04-07 13:34:11 +02:00
background - > colorize ( PlayerColor : : NEUTRAL ) ;
2017-07-20 06:08:49 +02:00
icon - > visible = false ;
icon - > setFrame ( 0 ) ;
amount - > setText ( " " ) ;
2011-12-22 16:05:19 +03:00
2017-07-20 06:08:49 +02:00
if ( stateIcon )
stateIcon - > visible = false ;
}
2012-05-13 18:04:21 +03:00
}