2017-07-13 10:26:03 +02:00
/*
* CTradeWindow . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2014-07-13 16:31:00 +03:00
# include "StdInc.h"
# include "CTradeWindow.h"
2014-07-13 20:53:37 +03:00
# include "../gui/CGuiHandler.h"
2023-01-05 19:34:37 +02:00
# include "../gui/CursorHandler.h"
2014-07-15 10:14:49 +03:00
# include "../widgets/Images.h"
2023-06-02 15:42:18 +02:00
# include "../render/Canvas.h"
2023-02-01 20:42:06 +02:00
# include "../gui/TextAlignment.h"
2023-04-27 19:21:06 +02:00
# include "../gui/Shortcut.h"
2023-05-16 14:10:26 +02:00
# include "../gui/WindowHandler.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/Buttons.h"
2023-05-30 16:31:45 +02:00
# include "../widgets/Slider.h"
2023-02-01 20:42:06 +02:00
# include "../widgets/TextControls.h"
2023-02-10 15:50:46 +02:00
# include "../windows/InfoWindows.h"
2014-07-13 16:31:00 +03:00
# include "../CGameInfo.h"
# include "../CPlayerInterface.h"
# include "../../CCallback.h"
# include "../../lib/VCMI_Lib.h"
# include "../../lib/CArtHandler.h"
# include "../../lib/CCreatureHandler.h"
# include "../../lib/CGeneralTextHandler.h"
# include "../../lib/CHeroHandler.h"
# include "../../lib/mapObjects/CGHeroInstance.h"
2014-07-15 10:14:49 +03:00
# include "../../lib/mapObjects/CGTownInstance.h"
# include "../../lib/mapObjects/CGMarket.h"
2023-10-23 12:59:15 +02:00
# include "../../lib/networkPacks/NetPacksBase.h"
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
CTradeWindow : : CTradeableItem : : CTradeableItem ( Point pos , EType Type , int ID , bool Left , int Serial )
2023-06-13 18:33:35 +02:00
: CIntObject ( LCLICK | HOVER | SHOW_POPUP , pos ) ,
2016-03-12 03:41:27 +02:00
type ( EType ( - 1 ) ) , // set to invalid, will be corrected in setType
id ( ID ) ,
serial ( Serial ) ,
left ( Left )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 16:31:00 +03:00
downSelection = false ;
hlp = nullptr ;
setType ( Type ) ;
}
void CTradeWindow : : CTradeableItem : : setType ( EType newType )
{
2018-04-07 13:34:11 +02:00
if ( type ! = newType )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 16:31:00 +03:00
type = newType ;
2018-04-07 13:34:11 +02:00
if ( getIndex ( ) < 0 )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
image = std : : make_shared < CAnimImage > ( getFilename ( ) , 0 ) ;
2014-07-13 16:31:00 +03:00
image - > disable ( ) ;
}
else
2018-04-07 13:34:11 +02:00
{
image = std : : make_shared < CAnimImage > ( getFilename ( ) , getIndex ( ) ) ;
}
2014-07-13 16:31:00 +03:00
}
}
void CTradeWindow : : CTradeableItem : : setID ( int newID )
{
if ( id ! = newID )
{
id = newID ;
if ( image )
{
int index = getIndex ( ) ;
if ( index < 0 )
image - > disable ( ) ;
else
{
image - > enable ( ) ;
image - > setFrame ( index ) ;
}
}
}
}
2023-08-23 14:07:50 +02:00
AnimationPath CTradeWindow : : CTradeableItem : : getFilename ( )
2014-07-13 16:31:00 +03:00
{
switch ( type )
{
case RESOURCE :
2023-08-23 14:07:50 +02:00
return AnimationPath : : builtin ( " RESOURCE " ) ;
2014-07-13 16:31:00 +03:00
case PLAYER :
2023-08-23 14:07:50 +02:00
return AnimationPath : : builtin ( " CREST58 " ) ;
2014-07-13 16:31:00 +03:00
case ARTIFACT_TYPE :
case ARTIFACT_PLACEHOLDER :
case ARTIFACT_INSTANCE :
2023-08-23 14:07:50 +02:00
return AnimationPath : : builtin ( " artifact " ) ;
2014-07-13 16:31:00 +03:00
case CREATURE :
2023-08-23 14:07:50 +02:00
return AnimationPath : : builtin ( " TWCRPORT " ) ;
2014-07-13 16:31:00 +03:00
default :
2023-08-23 14:07:50 +02:00
return { } ;
2014-07-13 16:31:00 +03:00
}
}
int CTradeWindow : : CTradeableItem : : getIndex ( )
{
if ( id < 0 )
return - 1 ;
switch ( type )
{
case RESOURCE :
case PLAYER :
return id ;
case ARTIFACT_TYPE :
case ARTIFACT_INSTANCE :
case ARTIFACT_PLACEHOLDER :
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 CGI - > artifacts ( ) - > getByIndex ( id ) - > getIconIndex ( ) ;
2014-07-13 16:31:00 +03:00
case CREATURE :
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 CGI - > creatures ( ) - > getByIndex ( id ) - > getIconIndex ( ) ;
2014-07-13 16:31:00 +03:00
default :
return - 1 ;
}
}
2023-06-02 15:42:18 +02:00
void CTradeWindow : : CTradeableItem : : showAll ( Canvas & to )
2014-07-13 16:31:00 +03:00
{
2014-12-25 21:03:19 +02:00
CTradeWindow * mw = dynamic_cast < CTradeWindow * > ( parent ) ;
assert ( mw ) ;
2014-07-13 16:31:00 +03:00
Point posToBitmap ;
Point posToSubCenter ;
switch ( type )
{
case RESOURCE :
posToBitmap = Point ( 19 , 9 ) ;
posToSubCenter = Point ( 36 , 59 ) ;
break ;
case CREATURE_PLACEHOLDER :
case CREATURE :
posToSubCenter = Point ( 29 , 76 ) ;
2014-12-25 21:03:19 +02:00
// Positing of unit count is different in Altar of Sacrifice and Freelancer's Guild
if ( mw - > mode = = EMarketMode : : CREATURE_EXP & & downSelection )
2014-07-13 16:31:00 +03:00
posToSubCenter . y + = 5 ;
break ;
case PLAYER :
posToSubCenter = Point ( 31 , 76 ) ;
break ;
case ARTIFACT_PLACEHOLDER :
case ARTIFACT_INSTANCE :
posToSubCenter = Point ( 19 , 55 ) ;
if ( downSelection )
posToSubCenter . y + = 8 ;
break ;
case ARTIFACT_TYPE :
posToSubCenter = Point ( 19 , 58 ) ;
break ;
}
if ( image )
{
image - > moveTo ( pos . topLeft ( ) + posToBitmap ) ;
CIntObject : : showAll ( to ) ;
}
2023-06-02 15:42:18 +02:00
to . drawText ( pos . topLeft ( ) + posToSubCenter , FONT_SMALL , Colors : : WHITE , ETextAlignment : : CENTER , subtitle ) ;
2014-07-13 16:31:00 +03:00
}
2023-07-08 13:33:04 +02:00
void CTradeWindow : : CTradeableItem : : clickPressed ( const Point & cursorPosition )
2014-07-13 16:31:00 +03:00
{
CTradeWindow * mw = dynamic_cast < CTradeWindow * > ( parent ) ;
assert ( mw ) ;
if ( type = = ARTIFACT_PLACEHOLDER )
{
CAltarWindow * aw = static_cast < CAltarWindow * > ( mw ) ;
2023-04-23 13:33:47 +02:00
const auto pickedArtInst = aw - > getPickedArtifact ( ) ;
if ( pickedArtInst )
2014-07-13 16:31:00 +03:00
{
2023-07-06 20:37:18 +02:00
aw - > arts - > pickedArtMoveToAltar ( ArtifactPosition : : TRANSITION_POS ) ;
2023-04-23 13:33:47 +02:00
aw - > moveArtToAltar ( this - > shared_from_this ( ) , pickedArtInst ) ;
2014-07-13 16:31:00 +03:00
}
else if ( const CArtifactInstance * art = getArtInstance ( ) )
{
2023-07-06 20:37:18 +02:00
const auto hero = aw - > arts - > getHero ( ) ;
2023-04-23 13:33:47 +02:00
const auto slot = hero - > getSlotByInstance ( art ) ;
assert ( slot ! = ArtifactPosition : : PRE_FIRST ) ;
LOCPLINT - > cb - > swapArtifacts ( ArtifactLocation ( hero , slot ) ,
ArtifactLocation ( hero , ArtifactPosition : : TRANSITION_POS ) ) ;
2023-07-06 20:37:18 +02:00
aw - > arts - > pickedArtFromSlot = slot ;
aw - > arts - > artifactsOnAltar . erase ( art ) ;
2014-07-13 16:31:00 +03:00
setID ( - 1 ) ;
2022-11-15 02:20:55 +02:00
subtitle . clear ( ) ;
2023-07-06 20:37:18 +02:00
aw - > deal - > block ( ! aw - > arts - > artifactsOnAltar . size ( ) ) ;
2014-07-13 16:31:00 +03:00
}
aw - > calcTotalExp ( ) ;
return ;
}
if ( left )
{
2018-04-07 13:34:11 +02:00
if ( mw - > hLeft ! = this - > shared_from_this ( ) )
mw - > hLeft = this - > shared_from_this ( ) ;
2014-07-13 16:31:00 +03:00
else
return ;
}
else
{
2018-04-07 13:34:11 +02:00
if ( mw - > hRight ! = this - > shared_from_this ( ) )
mw - > hRight = this - > shared_from_this ( ) ;
2014-07-13 16:31:00 +03:00
else
return ;
}
mw - > selectionChanged ( left ) ;
}
2023-06-02 15:42:18 +02:00
void CTradeWindow : : CTradeableItem : : showAllAt ( const Point & dstPos , const std : : string & customSub , Canvas & to )
2014-07-13 16:31:00 +03:00
{
Rect oldPos = pos ;
std : : string oldSub = subtitle ;
downSelection = true ;
moveTo ( dstPos ) ;
subtitle = customSub ;
showAll ( to ) ;
downSelection = false ;
moveTo ( oldPos . topLeft ( ) ) ;
subtitle = oldSub ;
}
void CTradeWindow : : CTradeableItem : : hover ( bool on )
{
if ( ! on )
{
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > clear ( ) ;
2014-07-13 16:31:00 +03:00
return ;
}
switch ( type )
{
case CREATURE :
case CREATURE_PLACEHOLDER :
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 481 ] ) % CGI - > creh - > objects [ id ] - > getNamePluralTranslated ( ) ) ) ;
2014-07-13 16:31:00 +03:00
break ;
case ARTIFACT_PLACEHOLDER :
if ( id < 0 )
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( CGI - > generaltexth - > zelp [ 582 ] . first ) ;
2014-07-13 16:31:00 +03:00
else
2023-05-16 17:34:23 +02:00
GH . statusbar ( ) - > write ( CGI - > artifacts ( ) - > getByIndex ( id ) - > getNameTranslated ( ) ) ;
2014-07-13 16:31:00 +03:00
break ;
}
}
2023-07-08 13:33:04 +02:00
void CTradeWindow : : CTradeableItem : : showPopupWindow ( const Point & cursorPosition )
2014-07-13 16:31:00 +03:00
{
2023-06-11 17:20:10 +02:00
switch ( type )
2014-07-13 16:31:00 +03:00
{
case CREATURE :
case CREATURE_PLACEHOLDER :
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
//GH.statusbar->print(boost::str(boost::format(CGI->generaltexth->allTexts[481]) % CGI->creh->objects[id]->namePl));
2014-07-13 16:31:00 +03:00
break ;
case ARTIFACT_TYPE :
case ARTIFACT_PLACEHOLDER :
2016-03-12 02:19:38 +02:00
//TODO: it's would be better for market to contain actual CArtifactInstance and not just ids of certain artifact type so we can use getEffectiveDescription.
2014-07-13 16:31:00 +03:00
if ( id > = 0 )
2023-02-10 15:50:46 +02:00
CRClickPopup : : createAndPush ( CGI - > artifacts ( ) - > getByIndex ( id ) - > getDescriptionTranslated ( ) ) ;
2014-07-13 16:31:00 +03:00
break ;
}
}
2017-07-15 13:08:20 +02:00
std : : string CTradeWindow : : CTradeableItem : : getName ( int number ) const
2014-07-13 16:31:00 +03:00
{
switch ( type )
{
case PLAYER :
return CGI - > generaltexth - > capColors [ id ] ;
case RESOURCE :
return CGI - > generaltexth - > restypes [ id ] ;
case CREATURE :
if ( number = = 1 )
2023-01-02 18:00:51 +02:00
return CGI - > creh - > objects [ id ] - > getNameSingularTranslated ( ) ;
2014-07-13 16:31:00 +03:00
else
2023-01-02 18:00:51 +02:00
return CGI - > creh - > objects [ id ] - > getNamePluralTranslated ( ) ;
2014-07-13 16:31:00 +03:00
case ARTIFACT_TYPE :
case ARTIFACT_INSTANCE :
2023-01-02 15:58:56 +02:00
return CGI - > artifacts ( ) - > getByIndex ( id ) - > getNameTranslated ( ) ;
2014-07-13 16:31:00 +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
logGlobal - > error ( " Invalid trade item type: %d " , ( int ) type ) ;
2014-07-13 16:31:00 +03:00
return " " ;
}
const CArtifactInstance * CTradeWindow : : CTradeableItem : : getArtInstance ( ) const
{
switch ( type )
{
case ARTIFACT_PLACEHOLDER :
case ARTIFACT_INSTANCE :
2018-04-07 13:34:11 +02:00
return hlp ;
2014-07-13 16:31:00 +03:00
default :
return nullptr ;
}
}
void CTradeWindow : : CTradeableItem : : setArtInstance ( const CArtifactInstance * art )
{
assert ( type = = ARTIFACT_PLACEHOLDER | | type = = ARTIFACT_INSTANCE ) ;
hlp = art ;
if ( art )
2023-01-02 15:58:56 +02:00
setID ( art - > artType - > getId ( ) ) ;
2014-07-13 16:31:00 +03:00
else
setID ( - 1 ) ;
}
2023-09-28 00:17:05 +02:00
CTradeWindow : : CTradeWindow ( const ImagePath & bgName , const IMarket * Market , const CGHeroInstance * Hero , const std : : function < void ( ) > & onWindowClosed , EMarketMode Mode ) :
2016-03-12 03:41:27 +02:00
CWindowObject ( PLAYER_COLORED , bgName ) ,
2014-07-13 16:31:00 +03:00
market ( Market ) ,
2023-09-28 00:17:05 +02:00
onWindowClosed ( onWindowClosed ) ,
2016-03-12 03:41:27 +02:00
hero ( Hero ) ,
readyToTrade ( false )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 16:31:00 +03:00
mode = Mode ;
initTypes ( ) ;
}
void CTradeWindow : : initTypes ( )
{
switch ( mode )
{
case EMarketMode : : RESOURCE_RESOURCE :
itemsType [ 1 ] = RESOURCE ;
itemsType [ 0 ] = RESOURCE ;
break ;
case EMarketMode : : RESOURCE_PLAYER :
itemsType [ 1 ] = RESOURCE ;
itemsType [ 0 ] = PLAYER ;
break ;
case EMarketMode : : CREATURE_RESOURCE :
itemsType [ 1 ] = CREATURE ;
itemsType [ 0 ] = RESOURCE ;
break ;
case EMarketMode : : RESOURCE_ARTIFACT :
itemsType [ 1 ] = RESOURCE ;
itemsType [ 0 ] = ARTIFACT_TYPE ;
break ;
case EMarketMode : : ARTIFACT_RESOURCE :
itemsType [ 1 ] = ARTIFACT_INSTANCE ;
itemsType [ 0 ] = RESOURCE ;
break ;
case EMarketMode : : CREATURE_EXP :
itemsType [ 1 ] = CREATURE ;
itemsType [ 0 ] = CREATURE_PLACEHOLDER ;
break ;
case EMarketMode : : ARTIFACT_EXP :
itemsType [ 1 ] = ARTIFACT_TYPE ;
itemsType [ 0 ] = ARTIFACT_PLACEHOLDER ;
break ;
}
}
void CTradeWindow : : initItems ( bool Left )
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 16:31:00 +03:00
if ( Left & & ( itemsType [ 1 ] = = ARTIFACT_TYPE | | itemsType [ 1 ] = = ARTIFACT_INSTANCE ) )
{
if ( mode = = EMarketMode : : ARTIFACT_RESOURCE )
{
2018-04-07 13:34:11 +02:00
auto item = std : : make_shared < CTradeableItem > ( Point ( 137 , 469 ) , itemsType [ Left ] , - 1 , 1 , 0 ) ;
item - > recActions & = ~ ( UPDATE | SHOWALL ) ;
items [ Left ] . push_back ( item ) ;
2014-07-13 16:31:00 +03:00
}
}
2018-04-07 13:34:11 +02:00
else
{
std : : vector < int > * ids = getItemsIds ( Left ) ;
std : : vector < Rect > pos ;
int amount = - 1 ;
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
getPositionsFor ( pos , Left , itemsType [ Left ] ) ;
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
if ( Left | | ! ids )
amount = 7 ;
else
2020-10-01 10:38:06 +02:00
amount = static_cast < int > ( ids - > size ( ) ) ;
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
if ( ids )
vstd : : amin ( amount , ids - > size ( ) ) ;
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
for ( int j = 0 ; j < amount ; j + + )
{
int id = ( ids & & ids - > size ( ) > j ) ? ( * ids ) [ j ] : j ;
if ( id < 0 & & mode ! = EMarketMode : : ARTIFACT_EXP ) //when sacrificing artifacts we need to prepare empty slots
continue ;
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
auto item = std : : make_shared < CTradeableItem > ( pos [ j ] . topLeft ( ) , itemsType [ Left ] , id , Left , j ) ;
item - > pos = pos [ j ] + this - > pos . topLeft ( ) ;
items [ Left ] . push_back ( item ) ;
}
vstd : : clear_pointer ( ids ) ;
initSubs ( Left ) ;
2014-07-13 16:31:00 +03:00
}
}
std : : vector < int > * CTradeWindow : : getItemsIds ( bool Left )
{
std : : vector < int > * ids = nullptr ;
if ( mode = = EMarketMode : : ARTIFACT_EXP )
return new std : : vector < int > ( 22 , - 1 ) ;
if ( Left )
{
switch ( itemsType [ 1 ] )
{
case CREATURE :
ids = new std : : vector < int > ;
for ( int i = 0 ; i < 7 ; i + + )
{
if ( const CCreature * c = hero - > getCreature ( SlotID ( i ) ) )
2023-04-05 02:26:29 +02:00
ids - > push_back ( c - > getId ( ) ) ;
2014-07-13 16:31:00 +03:00
else
ids - > push_back ( - 1 ) ;
}
break ;
}
}
else
{
switch ( itemsType [ 0 ] )
{
case PLAYER :
ids = new std : : vector < int > ;
for ( int i = 0 ; i < PlayerColor : : PLAYER_LIMIT_I ; i + + )
if ( PlayerColor ( i ) ! = LOCPLINT - > playerID & & LOCPLINT - > cb - > getPlayerStatus ( PlayerColor ( i ) ) = = EPlayerStatus : : INGAME )
ids - > push_back ( i ) ;
break ;
case ARTIFACT_TYPE :
ids = new std : : vector < int > ( market - > availableItemsIds ( mode ) ) ;
break ;
}
}
return ids ;
}
void CTradeWindow : : getPositionsFor ( std : : vector < Rect > & poss , bool Left , EType type ) const
{
if ( mode = = EMarketMode : : ARTIFACT_EXP & & ! Left )
{
//22 boxes, 5 in row, last row: two boxes centered
int h , w , x , y , dx , dy ;
h = w = 44 ;
x = 317 ;
y = 53 ;
dx = 54 ;
dy = 70 ;
for ( int i = 0 ; i < 4 ; i + + )
for ( int j = 0 ; j < 5 ; j + + )
2014-10-03 23:34:13 +03:00
poss . push_back ( Rect ( x + dx * j , y + dy * i , w , h ) ) ;
2014-07-13 16:31:00 +03:00
2020-10-06 01:27:04 +02:00
poss . push_back ( Rect ( ( int ) ( x + dx * 1.5 ) , ( y + dy * 4 ) , w , h ) ) ;
poss . push_back ( Rect ( ( int ) ( x + dx * 2.5 ) , ( y + dy * 4 ) , w , h ) ) ;
2014-07-13 16:31:00 +03:00
}
else
{
//seven boxes:
// X X X
// X X X
// X
int h , w , x , y , dx , dy ;
int leftToRightOffset ;
getBaseForPositions ( type , dx , dy , x , y , h , w , ! Left , leftToRightOffset ) ;
2016-01-21 19:23:45 +02:00
const std : : vector < Rect > tmp =
2014-10-03 23:34:13 +03:00
{
2023-03-15 12:17:08 +02:00
Rect ( Point ( x + 0 * dx , y + 0 * dx ) , Point ( w , h ) ) ,
Rect ( Point ( x + 1 * dx , y + 0 * dx ) , Point ( w , h ) ) ,
Rect ( Point ( x + 2 * dx , y + 0 * dx ) , Point ( w , h ) ) ,
Rect ( Point ( x + 0 * dx , y + 1 * dy ) , Point ( w , h ) ) ,
Rect ( Point ( x + 1 * dx , y + 1 * dy ) , Point ( w , h ) ) ,
Rect ( Point ( x + 2 * dx , y + 1 * dy ) , Point ( w , h ) ) ,
Rect ( Point ( x + 1 * dx , y + 2 * dy ) , Point ( w , h ) )
2014-10-03 23:34:13 +03:00
} ;
2016-01-21 19:23:45 +02:00
2014-10-03 23:34:13 +03:00
vstd : : concatenate ( poss , tmp ) ;
2014-07-13 16:31:00 +03:00
if ( ! Left )
{
for ( Rect & r : poss )
r . x + = leftToRightOffset ;
}
}
}
void CTradeWindow : : initSubs ( bool Left )
{
2018-04-07 13:34:11 +02:00
for ( auto item : items [ Left ] )
2014-07-13 16:31:00 +03:00
{
if ( Left )
{
switch ( itemsType [ 1 ] )
{
case CREATURE :
2023-03-09 15:36:46 +02:00
item - > subtitle = std : : to_string ( hero - > getStackCount ( SlotID ( item - > serial ) ) ) ;
2014-07-13 16:31:00 +03:00
break ;
case RESOURCE :
2023-04-05 02:26:29 +02:00
item - > subtitle = std : : to_string ( LOCPLINT - > cb - > getResourceAmount ( static_cast < EGameResID > ( item - > serial ) ) ) ;
2014-07-13 16:31:00 +03:00
break ;
}
}
else //right side
{
if ( itemsType [ 0 ] = = PLAYER )
{
2018-04-07 13:34:11 +02:00
item - > subtitle = CGI - > generaltexth - > capColors [ item - > id ] ;
2014-07-13 16:31:00 +03:00
}
else if ( hLeft ) //artifact, creature
{
int h1 , h2 ; //hlp variables for getting offer
2018-04-07 13:34:11 +02:00
market - > getOffer ( hLeft - > id , item - > id , h1 , h2 , mode ) ;
if ( item - > id ! = hLeft - > id | | mode ! = EMarketMode : : RESOURCE_RESOURCE ) //don't allow exchanging same resources
2014-07-13 16:31:00 +03:00
{
std : : ostringstream oss ;
oss < < h2 ;
if ( h1 ! = 1 )
oss < < " / " < < h1 ;
2018-04-07 13:34:11 +02:00
item - > subtitle = oss . str ( ) ;
2014-07-13 16:31:00 +03:00
}
else
2018-04-07 13:34:11 +02:00
item - > subtitle = CGI - > generaltexth - > allTexts [ 164 ] ; // n/a
2014-07-13 16:31:00 +03:00
}
else
2018-04-07 13:34:11 +02:00
item - > subtitle = " " ;
2014-07-13 16:31:00 +03:00
}
}
}
2023-06-02 15:42:18 +02:00
void CTradeWindow : : showAll ( Canvas & to )
2014-07-13 16:31:00 +03:00
{
CWindowObject : : showAll ( to ) ;
if ( hRight )
2023-06-02 15:42:18 +02:00
to . drawBorder ( Rect : : createAround ( hRight - > pos , 1 ) , Colors : : BRIGHT_YELLOW , 2 ) ;
2014-07-13 16:31:00 +03:00
if ( hLeft & & hLeft - > type ! = ARTIFACT_INSTANCE )
2023-06-02 15:42:18 +02:00
to . drawBorder ( Rect : : createAround ( hLeft - > pos , 1 ) , Colors : : BRIGHT_YELLOW , 2 ) ;
2014-07-13 16:31:00 +03:00
if ( readyToTrade )
{
2017-07-29 19:22:58 +02:00
if ( hLeft )
hLeft - > showAllAt ( pos . topLeft ( ) + selectionOffset ( true ) , selectionSubtitle ( true ) , to ) ;
if ( hRight )
hRight - > showAllAt ( pos . topLeft ( ) + selectionOffset ( false ) , selectionSubtitle ( false ) , to ) ;
2014-07-13 16:31:00 +03:00
}
}
2023-09-28 00:17:05 +02:00
void CTradeWindow : : close ( )
{
if ( onWindowClosed )
onWindowClosed ( ) ;
CWindowObject : : close ( ) ;
}
2018-04-07 13:34:11 +02:00
void CTradeWindow : : removeItems ( const std : : set < std : : shared_ptr < CTradeableItem > > & toRemove )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
for ( auto item : toRemove )
removeItem ( item ) ;
2014-07-13 16:31:00 +03:00
}
2018-04-07 13:34:11 +02:00
void CTradeWindow : : removeItem ( std : : shared_ptr < CTradeableItem > item )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
items [ item - > left ] - = item ;
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
if ( hRight = = item )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
hRight . reset ( ) ;
2014-07-13 16:31:00 +03:00
selectionChanged ( false ) ;
}
}
2018-04-07 13:34:11 +02:00
void CTradeWindow : : getEmptySlots ( std : : set < std : : shared_ptr < CTradeableItem > > & toRemove )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
for ( auto item : items [ 1 ] )
if ( ! hero - > getStackCount ( SlotID ( item - > serial ) ) )
toRemove . insert ( item ) ;
2014-07-13 16:31:00 +03:00
}
2023-08-19 20:43:50 +02:00
void CTradeWindow : : setMode ( EMarketMode Mode )
2014-07-13 16:31:00 +03:00
{
const IMarket * m = market ;
const CGHeroInstance * h = hero ;
2023-09-28 00:17:05 +02:00
const auto functor = onWindowClosed ;
2014-07-13 16:31:00 +03:00
2023-09-28 00:17:05 +02:00
onWindowClosed = nullptr ; // don't call on closing of this window - pass it to next window
2018-07-25 00:36:48 +02:00
close ( ) ;
2014-07-13 16:31:00 +03:00
switch ( Mode )
{
case EMarketMode : : CREATURE_EXP :
case EMarketMode : : ARTIFACT_EXP :
2023-09-28 00:17:05 +02:00
GH . windows ( ) . createAndPushWindow < CAltarWindow > ( m , h , functor , Mode ) ;
2014-07-13 16:31:00 +03:00
break ;
default :
2023-09-28 00:17:05 +02:00
GH . windows ( ) . createAndPushWindow < CMarketplaceWindow > ( m , h , functor , Mode ) ;
2014-07-13 16:31:00 +03:00
break ;
}
}
2016-11-04 18:54:09 +02:00
void CTradeWindow : : artifactSelected ( CHeroArtPlace * slot )
2014-07-13 16:31:00 +03:00
{
assert ( mode = = EMarketMode : : ARTIFACT_RESOURCE ) ;
2023-04-23 13:33:47 +02:00
items [ 1 ] [ 0 ] - > setArtInstance ( slot - > getArt ( ) ) ;
if ( slot - > getArt ( ) )
2014-07-13 16:31:00 +03:00
hLeft = items [ 1 ] [ 0 ] ;
else
hLeft = nullptr ;
selectionChanged ( true ) ;
}
2023-08-23 14:07:50 +02:00
ImagePath CMarketplaceWindow : : getBackgroundForMode ( EMarketMode mode )
2014-07-13 16:31:00 +03:00
{
switch ( mode )
{
case EMarketMode : : RESOURCE_RESOURCE :
2023-08-23 14:07:50 +02:00
return ImagePath : : builtin ( " TPMRKRES.bmp " ) ;
2014-07-13 16:31:00 +03:00
case EMarketMode : : RESOURCE_PLAYER :
2023-08-23 14:07:50 +02:00
return ImagePath : : builtin ( " TPMRKPTS.bmp " ) ;
2014-07-13 16:31:00 +03:00
case EMarketMode : : CREATURE_RESOURCE :
2023-08-23 14:07:50 +02:00
return ImagePath : : builtin ( " TPMRKCRS.bmp " ) ;
2014-07-13 16:31:00 +03:00
case EMarketMode : : RESOURCE_ARTIFACT :
2023-08-23 14:07:50 +02:00
return ImagePath : : builtin ( " TPMRKABS.bmp " ) ;
2014-07-13 16:31:00 +03:00
case EMarketMode : : ARTIFACT_RESOURCE :
2023-08-23 14:07:50 +02:00
return ImagePath : : builtin ( " TPMRKASS.bmp " ) ;
2014-07-13 16:31:00 +03:00
}
assert ( 0 ) ;
2023-08-23 14:07:50 +02:00
return { } ;
2014-07-13 16:31:00 +03:00
}
2023-09-28 00:17:05 +02:00
CMarketplaceWindow : : CMarketplaceWindow ( const IMarket * Market , const CGHeroInstance * Hero , const std : : function < void ( ) > & onWindowClosed , EMarketMode Mode )
: CTradeWindow ( getBackgroundForMode ( Mode ) , Market , Hero , onWindowClosed , Mode )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 16:31:00 +03:00
madeTransaction = false ;
2023-04-29 14:10:30 +02:00
bool sliderNeeded = ( mode ! = EMarketMode : : RESOURCE_ARTIFACT & & mode ! = EMarketMode : : ARTIFACT_RESOURCE ) ;
2014-07-13 16:31:00 +03:00
2022-11-29 17:07:21 +02:00
statusBar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2014-07-13 16:31:00 +03:00
std : : string title ;
2023-04-26 22:18:43 +02:00
if ( auto * o = dynamic_cast < const CGTownInstance * > ( market ) )
2014-07-13 16:31:00 +03:00
{
switch ( mode )
{
2018-04-07 13:34:11 +02:00
case EMarketMode : : CREATURE_RESOURCE :
2023-01-04 15:17:50 +02:00
title = ( * CGI - > townh ) [ ETownType : : STRONGHOLD ] - > town - > buildings [ BuildingID : : FREELANCERS_GUILD ] - > getNameTranslated ( ) ;
2018-04-07 13:34:11 +02:00
break ;
case EMarketMode : : RESOURCE_ARTIFACT :
2023-04-26 22:18:43 +02:00
title = ( * CGI - > townh ) [ o - > subID ] - > town - > buildings [ BuildingID : : ARTIFACT_MERCHANT ] - > getNameTranslated ( ) ;
2018-04-07 13:34:11 +02:00
break ;
case EMarketMode : : ARTIFACT_RESOURCE :
2023-04-26 22:18:43 +02:00
title = ( * CGI - > townh ) [ o - > subID ] - > town - > buildings [ BuildingID : : ARTIFACT_MERCHANT ] - > getNameTranslated ( ) ;
2022-12-02 18:52:05 +02:00
// create image that copies part of background containing slot MISC_1 into position of slot MISC_5
// this is workaround for bug in H3 files where this slot for ragdoll on this screen is missing
2023-01-30 13:58:13 +02:00
images . push_back ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 20 , 187 , 47 , 47 ) , 18 , 339 ) ) ;
2018-04-07 13:34:11 +02:00
break ;
default :
2014-07-13 16:31:00 +03:00
title = CGI - > generaltexth - > allTexts [ 158 ] ;
2018-04-07 13:34:11 +02:00
break ;
2014-07-13 16:31:00 +03:00
}
}
2023-04-29 14:10:30 +02:00
else if ( auto * o = dynamic_cast < const CGMarket * > ( market ) )
2014-07-13 16:31:00 +03:00
{
2023-04-29 17:08:42 +02:00
title = o - > title ;
2014-07-13 16:31:00 +03:00
}
2022-11-26 23:12:20 +02:00
titleLabel = std : : make_shared < CLabel > ( 300 , 27 , FONT_BIG , ETextAlignment : : CENTER , Colors : : YELLOW , title ) ;
2023-07-06 20:37:18 +02:00
if ( mode = = EMarketMode : : ARTIFACT_RESOURCE )
{
arts = std : : make_shared < CArtifactsOfHeroMarket > ( Point ( - 361 , 46 ) ) ;
arts - > selectArtCallback = std : : bind ( & CTradeWindow : : artifactSelected , this , _1 ) ;
arts - > setHero ( hero ) ;
2023-09-18 21:58:08 +02:00
addSetAndCallbacks ( arts ) ;
2023-07-06 20:37:18 +02:00
}
2014-07-13 16:31:00 +03:00
initItems ( false ) ;
initItems ( true ) ;
2023-08-23 14:07:50 +02:00
ok = std : : make_shared < CButton > ( Point ( 516 , 520 ) , AnimationPath : : builtin ( " IOK6432.DEF " ) , CGI - > generaltexth - > zelp [ 600 ] , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_RETURN ) ;
deal = std : : make_shared < CButton > ( Point ( 307 , 520 ) , AnimationPath : : builtin ( " TPMRKB.DEF " ) , CGI - > generaltexth - > zelp [ 595 ] , [ & ] ( ) { makeDeal ( ) ; } ) ;
2014-07-13 16:31:00 +03:00
deal - > block ( true ) ;
if ( sliderNeeded )
{
2023-06-22 22:49:38 +02:00
slider = std : : make_shared < CSlider > ( Point ( 231 , 490 ) , 137 , std : : bind ( & CMarketplaceWindow : : sliderMoved , this , _1 ) , 0 , 0 , 0 , Orientation : : HORIZONTAL ) ;
2023-08-23 14:07:50 +02:00
max = std : : make_shared < CButton > ( Point ( 229 , 520 ) , AnimationPath : : builtin ( " IRCBTNS.DEF " ) , CGI - > generaltexth - > zelp [ 596 ] , [ & ] ( ) { setMax ( ) ; } ) ;
2014-07-13 16:31:00 +03:00
max - > block ( true ) ;
}
else
{
deal - > moveBy ( Point ( - 30 , 0 ) ) ;
}
//left side
switch ( Mode )
{
case EMarketMode : : RESOURCE_RESOURCE :
case EMarketMode : : RESOURCE_PLAYER :
case EMarketMode : : RESOURCE_ARTIFACT :
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 154 , 148 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 270 ] ) ) ;
2014-07-13 16:31:00 +03:00
break ;
case EMarketMode : : CREATURE_RESOURCE :
//%s's Creatures
2023-01-02 13:27:03 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 152 , 102 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 272 ] ) % hero - > getNameTranslated ( ) ) ) ) ;
2014-07-13 16:31:00 +03:00
break ;
case EMarketMode : : ARTIFACT_RESOURCE :
//%s's Artifacts
2023-01-02 13:27:03 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 152 , 56 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 271 ] ) % hero - > getNameTranslated ( ) ) ) ) ;
2014-07-13 16:31:00 +03:00
break ;
}
2018-04-07 13:34:11 +02:00
Rect traderTextRect ;
2014-07-13 16:31:00 +03:00
//right side
switch ( Mode )
{
case EMarketMode : : RESOURCE_RESOURCE :
case EMarketMode : : CREATURE_RESOURCE :
case EMarketMode : : RESOURCE_ARTIFACT :
case EMarketMode : : ARTIFACT_RESOURCE :
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 445 , 148 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 168 ] ) ) ;
2014-07-13 16:31:00 +03:00
traderTextRect = Rect ( 316 , 48 , 260 , 75 ) ;
break ;
case EMarketMode : : RESOURCE_PLAYER :
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 445 , 55 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : WHITE , CGI - > generaltexth - > allTexts [ 169 ] ) ) ;
2014-07-13 16:31:00 +03:00
traderTextRect = Rect ( 28 , 48 , 260 , 75 ) ;
break ;
}
2022-11-26 23:12:20 +02:00
traderText = std : : make_shared < CTextBox > ( " " , traderTextRect , 0 , FONT_SMALL , ETextAlignment : : CENTER ) ;
2014-07-13 16:31:00 +03:00
int specialOffset = mode = = EMarketMode : : ARTIFACT_RESOURCE ? 35 : 0 ; //in selling artifacts mode we need to move res-res and art-res buttons down
if ( printButtonFor ( EMarketMode : : RESOURCE_PLAYER ) )
2023-08-23 14:07:50 +02:00
buttons . push_back ( std : : make_shared < CButton > ( Point ( 18 , 520 ) , AnimationPath : : builtin ( " TPMRKBU1.DEF " ) , CGI - > generaltexth - > zelp [ 612 ] , [ & ] ( ) { setMode ( EMarketMode : : RESOURCE_PLAYER ) ; } ) ) ;
2014-07-13 16:31:00 +03:00
if ( printButtonFor ( EMarketMode : : RESOURCE_RESOURCE ) )
2023-08-23 14:07:50 +02:00
buttons . push_back ( std : : make_shared < CButton > ( Point ( 516 , 450 + specialOffset ) , AnimationPath : : builtin ( " TPMRKBU5.DEF " ) , CGI - > generaltexth - > zelp [ 605 ] , [ & ] ( ) { setMode ( EMarketMode : : RESOURCE_RESOURCE ) ; } ) ) ;
2014-07-13 16:31:00 +03:00
if ( printButtonFor ( EMarketMode : : CREATURE_RESOURCE ) )
2023-08-23 14:07:50 +02:00
buttons . push_back ( std : : make_shared < CButton > ( Point ( 516 , 485 ) , AnimationPath : : builtin ( " TPMRKBU4.DEF " ) , CGI - > generaltexth - > zelp [ 599 ] , [ & ] ( ) { setMode ( EMarketMode : : CREATURE_RESOURCE ) ; } ) ) ;
2014-07-13 16:31:00 +03:00
if ( printButtonFor ( EMarketMode : : RESOURCE_ARTIFACT ) )
2023-08-23 14:07:50 +02:00
buttons . push_back ( std : : make_shared < CButton > ( Point ( 18 , 450 + specialOffset ) , AnimationPath : : builtin ( " TPMRKBU2.DEF " ) , CGI - > generaltexth - > zelp [ 598 ] , [ & ] ( ) { setMode ( EMarketMode : : RESOURCE_ARTIFACT ) ; } ) ) ;
2014-07-13 16:31:00 +03:00
if ( printButtonFor ( EMarketMode : : ARTIFACT_RESOURCE ) )
2023-08-23 14:07:50 +02:00
buttons . push_back ( std : : make_shared < CButton > ( Point ( 18 , 485 ) , AnimationPath : : builtin ( " TPMRKBU3.DEF " ) , CGI - > generaltexth - > zelp [ 613 ] , [ & ] ( ) { setMode ( EMarketMode : : ARTIFACT_RESOURCE ) ; } ) ) ;
2014-07-13 16:31:00 +03:00
updateTraderText ( ) ;
}
2018-04-07 13:34:11 +02:00
CMarketplaceWindow : : ~ CMarketplaceWindow ( ) = default ;
2014-07-13 16:31:00 +03:00
void CMarketplaceWindow : : setMax ( )
{
2023-05-30 17:10:22 +02:00
slider - > scrollToMax ( ) ;
2014-07-13 16:31:00 +03:00
}
void CMarketplaceWindow : : makeDeal ( )
{
int sliderValue = 0 ;
if ( slider )
2014-08-03 17:31:56 +03:00
sliderValue = slider - > getValue ( ) ;
2014-07-13 16:31:00 +03:00
else
sliderValue = ! deal - > isBlocked ( ) ; //should always be 1
if ( ! sliderValue )
return ;
2023-03-21 20:02:58 +02:00
bool allowDeal = true ;
2023-03-20 01:18:32 +02:00
int leftIdToSend = hLeft - > id ;
2014-07-13 16:31:00 +03:00
switch ( mode )
{
case EMarketMode : : CREATURE_RESOURCE :
leftIdToSend = hLeft - > serial ;
break ;
case EMarketMode : : ARTIFACT_RESOURCE :
2023-07-03 22:11:56 +02:00
leftIdToSend = hLeft - > getArtInstance ( ) - > getId ( ) . getNum ( ) ;
2014-07-13 16:31:00 +03:00
break ;
2023-03-20 01:18:32 +02:00
case EMarketMode : : RESOURCE_ARTIFACT :
2023-03-21 12:13:53 +02:00
if ( ! ArtifactID ( hRight - > id ) . toArtifact ( ) - > canBePutAt ( hero ) )
2023-03-20 01:18:32 +02:00
{
2023-03-21 20:02:58 +02:00
LOCPLINT - > showInfoDialog ( CGI - > generaltexth - > translate ( " core.genrltxt.326 " ) ) ;
allowDeal = false ;
2023-03-20 01:18:32 +02:00
}
break ;
2014-07-13 16:31:00 +03:00
default :
break ;
}
2023-03-21 20:02:58 +02:00
if ( allowDeal )
2014-07-13 16:31:00 +03:00
{
2023-03-20 01:18:32 +02:00
if ( slider )
{
2023-04-28 03:14:27 +02:00
LOCPLINT - > cb - > trade ( market , mode , leftIdToSend , hRight - > id , slider - > getValue ( ) * r1 , hero ) ;
2023-05-30 17:10:22 +02:00
slider - > scrollTo ( 0 ) ;
2023-03-20 01:18:32 +02:00
}
else
{
2023-04-28 03:14:27 +02:00
LOCPLINT - > cb - > trade ( market , mode , leftIdToSend , hRight - > id , r2 , hero ) ;
2023-03-20 01:18:32 +02:00
}
2014-07-13 16:31:00 +03:00
}
2023-03-21 20:02:58 +02:00
madeTransaction = true ;
2014-07-13 16:31:00 +03:00
hLeft = nullptr ;
hRight = nullptr ;
selectionChanged ( true ) ;
}
void CMarketplaceWindow : : sliderMoved ( int to )
{
redraw ( ) ;
}
void CMarketplaceWindow : : selectionChanged ( bool side )
{
readyToTrade = hLeft & & hRight ;
if ( mode = = EMarketMode : : RESOURCE_RESOURCE )
readyToTrade = readyToTrade & & ( hLeft - > id ! = hRight - > id ) ; //for resource trade, two DIFFERENT resources must be selected
2020-10-06 01:27:04 +02:00
if ( mode = = EMarketMode : : ARTIFACT_RESOURCE & & ! hLeft )
2023-04-23 13:33:47 +02:00
arts - > unmarkSlots ( ) ;
2014-07-13 16:31:00 +03:00
if ( readyToTrade )
{
int soldItemId = hLeft - > id ;
market - > getOffer ( soldItemId , hRight - > id , r1 , r2 , mode ) ;
if ( slider )
{
int newAmount = - 1 ;
if ( itemsType [ 1 ] = = RESOURCE )
2023-04-05 02:26:29 +02:00
newAmount = LOCPLINT - > cb - > getResourceAmount ( static_cast < EGameResID > ( soldItemId ) ) ;
2014-07-13 16:31:00 +03:00
else if ( itemsType [ 1 ] = = CREATURE )
2015-12-24 20:30:57 +02:00
newAmount = hero - > getStackCount ( SlotID ( hLeft - > serial ) ) - ( hero - > stacksCount ( ) = = 1 & & hero - > needsLastStack ( ) ) ;
2014-07-13 16:31:00 +03:00
else
assert ( 0 ) ;
slider - > setAmount ( newAmount / r1 ) ;
2023-05-30 17:10:22 +02:00
slider - > scrollTo ( 0 ) ;
2014-07-13 16:31:00 +03:00
max - > block ( false ) ;
deal - > block ( false ) ;
}
else if ( itemsType [ 1 ] = = RESOURCE ) //buying -> check if we can afford transaction
{
2023-04-05 02:26:29 +02:00
deal - > block ( LOCPLINT - > cb - > getResourceAmount ( static_cast < EGameResID > ( soldItemId ) ) < r1 ) ;
2014-07-13 16:31:00 +03:00
}
else
deal - > block ( false ) ;
}
else
{
if ( slider )
{
max - > block ( true ) ;
slider - > setAmount ( 0 ) ;
2023-05-30 17:10:22 +02:00
slider - > scrollTo ( 0 ) ;
2014-07-13 16:31:00 +03:00
}
deal - > block ( true ) ;
}
if ( side & & itemsType [ 0 ] ! = PLAYER ) //items[1] selection changed, recalculate offers
initSubs ( false ) ;
updateTraderText ( ) ;
redraw ( ) ;
}
2023-08-19 20:43:50 +02:00
bool CMarketplaceWindow : : printButtonFor ( EMarketMode M ) const
2014-07-13 16:31:00 +03:00
{
2023-09-18 16:22:30 +02:00
if ( ! market - > allowsTrade ( M ) )
return false ;
if ( M = = mode )
return false ;
if ( M = = EMarketMode : : RESOURCE_RESOURCE | | M = = EMarketMode : : RESOURCE_PLAYER )
{
auto * town = dynamic_cast < const CGTownInstance * > ( market ) ;
if ( town )
return town - > getOwner ( ) = = LOCPLINT - > playerID ;
else
return true ;
}
else
{
return hero ! = nullptr ;
}
2014-07-13 16:31:00 +03:00
}
void CMarketplaceWindow : : garrisonChanged ( )
{
if ( mode ! = EMarketMode : : CREATURE_RESOURCE )
return ;
2018-04-07 13:34:11 +02:00
std : : set < std : : shared_ptr < CTradeableItem > > toRemove ;
2014-07-13 16:31:00 +03:00
getEmptySlots ( toRemove ) ;
removeItems ( toRemove ) ;
initSubs ( true ) ;
}
void CMarketplaceWindow : : artifactsChanged ( bool Left )
{
assert ( ! Left ) ;
if ( mode ! = EMarketMode : : RESOURCE_ARTIFACT )
return ;
std : : vector < int > available = market - > availableItemsIds ( mode ) ;
2018-04-07 13:34:11 +02:00
std : : set < std : : shared_ptr < CTradeableItem > > toRemove ;
for ( auto item : items [ 0 ] )
if ( ! vstd : : contains ( available , item - > id ) )
toRemove . insert ( item ) ;
2014-07-13 16:31:00 +03:00
removeItems ( toRemove ) ;
2023-03-25 23:31:14 +02:00
// clear set to erase final instance of shared_ptr - we want to redraw screen only after it has been deleted
toRemove . clear ( ) ;
2014-07-13 16:31:00 +03:00
redraw ( ) ;
}
std : : string CMarketplaceWindow : : selectionSubtitle ( bool Left ) const
{
if ( Left )
{
switch ( itemsType [ 1 ] )
{
case RESOURCE :
case CREATURE :
{
int val = slider
2014-08-03 17:31:56 +03:00
? slider - > getValue ( ) * r1
2014-07-13 16:31:00 +03:00
: ( ( ( deal - > isBlocked ( ) ) ) ? 0 : r1 ) ;
2023-03-09 15:36:46 +02:00
return std : : to_string ( val ) ;
2014-07-13 16:31:00 +03:00
}
case ARTIFACT_INSTANCE :
return ( ( deal - > isBlocked ( ) ) ? " 0 " : " 1 " ) ;
}
}
else
{
switch ( itemsType [ 0 ] )
{
case RESOURCE :
if ( slider )
2023-03-09 15:36:46 +02:00
return std : : to_string ( slider - > getValue ( ) * r2 ) ;
2014-07-13 16:31:00 +03:00
else
2023-03-09 15:36:46 +02:00
return std : : to_string ( r2 ) ;
2014-07-13 16:31:00 +03:00
case ARTIFACT_TYPE :
return ( ( deal - > isBlocked ( ) ) ? " 0 " : " 1 " ) ;
case PLAYER :
return ( hRight ? CGI - > generaltexth - > capColors [ hRight - > id ] : " " ) ;
}
}
return " ??? " ;
}
Point CMarketplaceWindow : : selectionOffset ( bool Left ) const
{
if ( Left )
{
switch ( itemsType [ 1 ] )
{
case RESOURCE :
return Point ( 122 , 446 ) ;
case CREATURE :
return Point ( 128 , 450 ) ;
case ARTIFACT_INSTANCE :
return Point ( 134 , 466 ) ;
}
}
else
{
switch ( itemsType [ 0 ] )
{
case RESOURCE :
if ( mode = = EMarketMode : : ARTIFACT_RESOURCE )
return Point ( 410 , 469 ) ;
else
return Point ( 410 , 446 ) ;
case ARTIFACT_TYPE :
return Point ( 425 , 447 ) ;
case PLAYER :
return Point ( 417 , 451 ) ;
}
}
assert ( 0 ) ;
return Point ( 0 , 0 ) ;
}
2016-11-26 14:14:43 +02:00
void CMarketplaceWindow : : resourceChanged ( )
2014-07-13 16:31:00 +03:00
{
initSubs ( true ) ;
}
void CMarketplaceWindow : : getBaseForPositions ( EType type , int & dx , int & dy , int & x , int & y , int & h , int & w , bool Right , int & leftToRightOffset ) const
{
switch ( type )
{
case RESOURCE :
dx = 82 ;
dy = 79 ;
x = 39 ;
y = 180 ;
2014-12-24 02:22:48 +02:00
h = 68 ;
w = 70 ;
2014-07-13 16:31:00 +03:00
break ;
case PLAYER :
dx = 83 ;
dy = 118 ;
h = 64 ;
w = 58 ;
x = 44 ;
y = 83 ;
assert ( Right ) ;
break ;
case CREATURE : //45,123
x = 45 ;
y = 123 ;
w = 58 ;
h = 64 ;
dx = 83 ;
dy = 98 ;
assert ( ! Right ) ;
break ;
case ARTIFACT_TYPE : //45,123
x = 340 - 289 ;
y = 180 ;
w = 44 ;
h = 44 ;
dx = 83 ;
dy = 79 ;
break ;
}
leftToRightOffset = 289 ;
}
void CMarketplaceWindow : : updateTraderText ( )
{
if ( readyToTrade )
{
if ( mode = = EMarketMode : : RESOURCE_PLAYER )
{
//I can give %s to the %s player.
traderText - > setText ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 165 ] ) % hLeft - > getName ( ) % hRight - > getName ( ) ) ) ;
}
else if ( mode = = EMarketMode : : RESOURCE_ARTIFACT )
{
//I can offer you the %s for %d %s of %s.
traderText - > setText ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 267 ] ) % hRight - > getName ( ) % r1 % CGI - > generaltexth - > allTexts [ 160 + ( r1 = = 1 ) ] % hLeft - > getName ( ) ) ) ;
}
else if ( mode = = EMarketMode : : RESOURCE_RESOURCE )
{
//I can offer you %d %s of %s for %d %s of %s.
traderText - > setText ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 157 ] ) % r2 % CGI - > generaltexth - > allTexts [ 160 + ( r2 = = 1 ) ] % hRight - > getName ( ) % r1 % CGI - > generaltexth - > allTexts [ 160 + ( r1 = = 1 ) ] % hLeft - > getName ( ) ) ) ;
}
else if ( mode = = EMarketMode : : CREATURE_RESOURCE )
{
//I can offer you %d %s of %s for %d %s.
traderText - > setText ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 269 ] ) % r2 % CGI - > generaltexth - > allTexts [ 160 + ( r2 = = 1 ) ] % hRight - > getName ( ) % r1 % hLeft - > getName ( r1 ) ) ) ;
}
else if ( mode = = EMarketMode : : ARTIFACT_RESOURCE )
{
//I can offer you %d %s of %s for your %s.
traderText - > setText ( boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 268 ] ) % r2 % CGI - > generaltexth - > allTexts [ 160 + ( r2 = = 1 ) ] % hRight - > getName ( ) % hLeft - > getName ( r1 ) ) ) ;
}
return ;
}
int gnrtxtnr = - 1 ;
if ( madeTransaction )
{
if ( mode = = EMarketMode : : RESOURCE_PLAYER )
gnrtxtnr = 166 ; //Are there any other resources you'd like to give away?
else
gnrtxtnr = 162 ; //You have received quite a bargain. I expect to make no profit on the deal. Can I interest you in any of my other wares?
}
else
{
if ( mode = = EMarketMode : : RESOURCE_PLAYER )
gnrtxtnr = 167 ; //If you'd like to give any of your resources to another player, click on the item you wish to give and to whom.
else
gnrtxtnr = 163 ; //Please inspect our fine wares. If you feel like offering a trade, click on the items you wish to trade with and for.
}
traderText - > setText ( CGI - > generaltexth - > allTexts [ gnrtxtnr ] ) ;
}
2023-09-28 00:17:05 +02:00
CAltarWindow : : CAltarWindow ( const IMarket * Market , const CGHeroInstance * Hero , const std : : function < void ( ) > & onWindowClosed , EMarketMode Mode )
: CTradeWindow ( ImagePath : : builtin ( Mode = = EMarketMode : : CREATURE_EXP ? " ALTARMON.bmp " : " ALTRART2.bmp " ) , Market , Hero , onWindowClosed , Mode )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 16:31:00 +03:00
if ( Mode = = EMarketMode : : CREATURE_EXP )
{
//%s's Creatures
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 155 , 30 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW ,
2023-01-02 13:27:03 +02:00
boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 272 ] ) % hero - > getNameTranslated ( ) ) ) ) ;
2014-07-13 16:31:00 +03:00
//Altar of Sacrifice
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 450 , 30 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 479 ] ) ) ;
2014-07-13 16:31:00 +03:00
//To sacrifice creatures, move them from your army on to the Altar and click Sacrifice
2022-11-26 23:12:20 +02:00
new CTextBox ( CGI - > generaltexth - > allTexts [ 480 ] , Rect ( 320 , 56 , 256 , 40 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW ) ;
2014-07-13 16:31:00 +03:00
2023-06-22 22:49:38 +02:00
slider = std : : make_shared < CSlider > ( Point ( 231 , 481 ) , 137 , std : : bind ( & CAltarWindow : : sliderMoved , this , _1 ) , 0 , 0 , 0 , Orientation : : HORIZONTAL ) ;
2023-08-23 14:07:50 +02:00
max = std : : make_shared < CButton > ( Point ( 147 , 520 ) , AnimationPath : : builtin ( " IRCBTNS.DEF " ) , CGI - > generaltexth - > zelp [ 578 ] , std : : bind ( & CSlider : : scrollToMax , slider ) ) ;
2014-07-13 16:31:00 +03:00
sacrificedUnits . resize ( GameConstants : : ARMY_SIZE , 0 ) ;
2023-08-23 14:07:50 +02:00
sacrificeAll = std : : make_shared < CButton > ( Point ( 393 , 520 ) , AnimationPath : : builtin ( " ALTARMY.DEF " ) , CGI - > generaltexth - > zelp [ 579 ] , std : : bind ( & CAltarWindow : : SacrificeAll , this ) ) ;
2014-07-13 16:31:00 +03:00
initItems ( true ) ;
mimicCres ( ) ;
}
else
{
//Sacrifice artifacts for experience
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 450 , 34 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 477 ] ) ) ;
2014-07-13 16:31:00 +03:00
//%s's Creatures
2022-11-26 23:12:20 +02:00
labels . push_back ( std : : make_shared < CLabel > ( 302 , 423 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW , CGI - > generaltexth - > allTexts [ 478 ] ) ) ;
2014-07-13 16:31:00 +03:00
2023-08-23 14:07:50 +02:00
sacrificeAll = std : : make_shared < CButton > ( Point ( 393 , 520 ) , AnimationPath : : builtin ( " ALTFILL.DEF " ) , CGI - > generaltexth - > zelp [ 571 ] , std : : bind ( & CAltarWindow : : SacrificeAll , this ) ) ;
2014-07-13 16:31:00 +03:00
sacrificeAll - > block ( hero - > artifactsInBackpack . empty ( ) & & hero - > artifactsWorn . empty ( ) ) ;
2023-08-23 14:07:50 +02:00
sacrificeBackpack = std : : make_shared < CButton > ( Point ( 147 , 520 ) , AnimationPath : : builtin ( " ALTEMBK.DEF " ) , CGI - > generaltexth - > zelp [ 570 ] , std : : bind ( & CAltarWindow : : SacrificeBackpack , this ) ) ;
2014-07-13 16:31:00 +03:00
sacrificeBackpack - > block ( hero - > artifactsInBackpack . empty ( ) ) ;
2023-07-06 20:37:18 +02:00
arts = std : : make_shared < CArtifactsOfHeroAltar > ( Point ( - 365 , - 12 ) ) ;
arts - > setHero ( hero ) ;
2023-09-18 21:58:08 +02:00
addSetAndCallbacks ( arts ) ;
2023-07-06 20:37:18 +02:00
2014-07-13 16:31:00 +03:00
initItems ( true ) ;
initItems ( false ) ;
2023-08-23 14:07:50 +02:00
artIcon = std : : make_shared < CAnimImage > ( AnimationPath : : builtin ( " ARTIFACT " ) , 0 , 0 , 281 , 442 ) ;
2014-07-13 16:31:00 +03:00
artIcon - > disable ( ) ;
}
//Experience needed to reach next level
2022-11-26 23:12:20 +02:00
texts . push_back ( std : : make_shared < CTextBox > ( CGI - > generaltexth - > allTexts [ 475 ] , Rect ( 15 , 415 , 125 , 50 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW ) ) ;
2014-07-13 16:31:00 +03:00
//Total experience on the Altar
2022-11-26 23:12:20 +02:00
texts . push_back ( std : : make_shared < CTextBox > ( CGI - > generaltexth - > allTexts [ 476 ] , Rect ( 15 , 495 , 125 , 40 ) , 0 , FONT_SMALL , ETextAlignment : : CENTER , Colors : : YELLOW ) ) ;
2014-07-13 16:31:00 +03:00
2022-11-29 17:07:21 +02:00
statusBar = CGStatusBar : : create ( std : : make_shared < CPicture > ( background - > getSurface ( ) , Rect ( 8 , pos . h - 26 , pos . w - 16 , 19 ) , 8 , pos . h - 26 ) ) ;
2014-07-13 16:31:00 +03:00
2023-08-23 14:07:50 +02:00
ok = std : : make_shared < CButton > ( Point ( 516 , 520 ) , AnimationPath : : builtin ( " IOK6432.DEF " ) , CGI - > generaltexth - > zelp [ 568 ] , [ & ] ( ) { close ( ) ; } , EShortcut : : GLOBAL_RETURN ) ;
2014-07-13 16:31:00 +03:00
2023-08-23 14:07:50 +02:00
deal = std : : make_shared < CButton > ( Point ( 269 , 520 ) , AnimationPath : : builtin ( " ALTSACR.DEF " ) , CGI - > generaltexth - > zelp [ 585 ] , std : : bind ( & CAltarWindow : : makeDeal , this ) ) ;
2014-07-13 16:31:00 +03:00
2014-12-25 05:20:40 +02:00
if ( Mode = = EMarketMode : : CREATURE_EXP )
{
2023-08-23 14:07:50 +02:00
auto changeMode = std : : make_shared < CButton > ( Point ( 516 , 421 ) , AnimationPath : : builtin ( " ALTART.DEF " ) , CGI - > generaltexth - > zelp [ 580 ] , std : : bind ( & CTradeWindow : : setMode , this , EMarketMode : : ARTIFACT_EXP ) ) ;
2018-04-07 13:34:11 +02:00
if ( Hero - > getAlignment ( ) = = : : EAlignment : : EVIL )
2014-12-25 05:20:40 +02:00
changeMode - > block ( true ) ;
2018-04-07 13:34:11 +02:00
buttons . push_back ( changeMode ) ;
2014-12-25 05:20:40 +02:00
}
2018-04-07 13:34:11 +02:00
else if ( Mode = = EMarketMode : : ARTIFACT_EXP )
2014-12-25 05:20:40 +02:00
{
2023-08-23 14:07:50 +02:00
auto changeMode = std : : make_shared < CButton > ( Point ( 516 , 421 ) , AnimationPath : : builtin ( " ALTSACC.DEF " ) , CGI - > generaltexth - > zelp [ 572 ] , std : : bind ( & CTradeWindow : : setMode , this , EMarketMode : : CREATURE_EXP ) ) ;
2018-04-07 13:34:11 +02:00
if ( Hero - > getAlignment ( ) = = : : EAlignment : : GOOD )
2014-12-25 05:20:40 +02:00
changeMode - > block ( true ) ;
2018-04-07 13:34:11 +02:00
buttons . push_back ( changeMode ) ;
2014-12-25 05:20:40 +02:00
}
2014-07-13 16:31:00 +03:00
expPerUnit . resize ( GameConstants : : ARMY_SIZE , 0 ) ;
getExpValues ( ) ;
2022-11-26 23:12:20 +02:00
expToLevel = std : : make_shared < CLabel > ( 73 , 475 , FONT_SMALL , ETextAlignment : : CENTER ) ;
expOnAltar = std : : make_shared < CLabel > ( 73 , 543 , FONT_SMALL , ETextAlignment : : CENTER ) ;
2014-07-13 16:31:00 +03:00
setExpToLevel ( ) ;
calcTotalExp ( ) ;
blockTrade ( ) ;
}
2018-04-07 13:34:11 +02:00
CAltarWindow : : ~ CAltarWindow ( ) = default ;
2014-07-13 16:31:00 +03:00
void CAltarWindow : : getBaseForPositions ( EType type , int & dx , int & dy , int & x , int & y , int & h , int & w , bool Right , int & leftToRightOffset ) const
{
leftToRightOffset = 289 ;
x = 45 ;
y = 110 ;
w = 58 ;
h = 64 ;
dx = 83 ;
dy = 98 ;
}
void CAltarWindow : : sliderMoved ( int to )
{
2014-12-26 00:18:58 +02:00
if ( hLeft )
sacrificedUnits [ hLeft - > serial ] = to ;
if ( hRight )
updateRight ( hRight ) ;
2014-07-13 16:31:00 +03:00
deal - > block ( ! to ) ;
calcTotalExp ( ) ;
redraw ( ) ;
}
void CAltarWindow : : makeDeal ( )
{
if ( mode = = EMarketMode : : CREATURE_EXP )
{
blockTrade ( ) ;
2023-05-30 17:10:22 +02:00
slider - > scrollTo ( 0 ) ;
2014-07-13 16:31:00 +03:00
2017-10-18 21:02:23 +02:00
std : : vector < ui32 > ids ;
std : : vector < ui32 > toSacrifice ;
2017-10-14 21:30:56 +02:00
2017-10-28 11:04:55 +02:00
for ( int i = 0 ; i < sacrificedUnits . size ( ) ; i + + )
2014-07-13 16:31:00 +03:00
{
2017-10-14 21:30:56 +02:00
if ( sacrificedUnits [ i ] )
{
ids . push_back ( i ) ;
toSacrifice . push_back ( sacrificedUnits [ i ] ) ;
}
2014-07-13 16:31:00 +03:00
}
2023-04-28 03:14:27 +02:00
LOCPLINT - > cb - > trade ( market , mode , ids , { } , toSacrifice , hero ) ;
2017-10-14 21:30:56 +02:00
2014-07-13 16:31:00 +03:00
for ( int & val : sacrificedUnits )
val = 0 ;
2018-04-07 13:34:11 +02:00
for ( auto item : items [ 0 ] )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
item - > setType ( CREATURE_PLACEHOLDER ) ;
item - > subtitle = " " ;
2014-07-13 16:31:00 +03:00
}
}
else
{
2017-10-18 21:02:23 +02:00
std : : vector < ui32 > positions ;
2023-07-06 20:37:18 +02:00
for ( const CArtifactInstance * art : arts - > artifactsOnAltar )
2014-07-13 16:31:00 +03:00
{
2023-04-23 13:33:47 +02:00
positions . push_back ( hero - > getSlotByInstance ( art ) ) ;
2014-07-13 16:31:00 +03:00
}
2023-04-23 13:33:47 +02:00
std : : sort ( positions . begin ( ) , positions . end ( ) , std : : greater < > ( ) ) ;
2017-10-14 21:30:56 +02:00
2023-04-28 03:14:27 +02:00
LOCPLINT - > cb - > trade ( market , mode , positions , { } , { } , hero ) ;
2023-07-06 20:37:18 +02:00
arts - > artifactsOnAltar . clear ( ) ;
2014-07-13 16:31:00 +03:00
2018-04-07 13:34:11 +02:00
for ( auto item : items [ 0 ] )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
item - > setID ( - 1 ) ;
item - > subtitle = " " ;
2014-07-13 16:31:00 +03:00
}
//arts->scrollBackpack(0);
deal - > block ( true ) ;
}
calcTotalExp ( ) ;
}
void CAltarWindow : : SacrificeAll ( )
{
if ( mode = = EMarketMode : : CREATURE_EXP )
{
bool movedAnything = false ;
2018-04-07 13:34:11 +02:00
for ( auto item : items [ 1 ] )
sacrificedUnits [ item - > serial ] = hero - > getStackCount ( SlotID ( item - > serial ) ) ;
2014-07-13 16:31:00 +03:00
sacrificedUnits [ items [ 1 ] . front ( ) - > serial ] - - ;
2018-04-07 13:34:11 +02:00
for ( auto item : items [ 0 ] )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
updateRight ( item ) ;
if ( item - > type = = CREATURE )
2014-07-13 16:31:00 +03:00
movedAnything = true ;
}
deal - > block ( ! movedAnything ) ;
calcTotalExp ( ) ;
}
else
{
2023-08-11 13:19:06 +02:00
std : : vector < ConstTransitivePtr < CArtifactInstance > > artsForMove ;
for ( const auto & slotInfo : arts - > visibleArtSet . artifactsWorn )
2014-07-13 16:31:00 +03:00
{
2023-08-11 13:19:06 +02:00
if ( ! slotInfo . second . locked & & slotInfo . second . artifact - > artType - > isTradable ( ) )
artsForMove . push_back ( slotInfo . second . artifact ) ;
2014-07-13 16:31:00 +03:00
}
2023-08-11 13:19:06 +02:00
for ( auto artInst : artsForMove )
moveArtToAltar ( nullptr , artInst ) ;
2023-07-06 20:37:18 +02:00
arts - > updateWornSlots ( ) ;
2014-07-13 16:31:00 +03:00
SacrificeBackpack ( ) ;
}
redraw ( ) ;
}
void CAltarWindow : : selectionChanged ( bool side )
{
if ( mode ! = EMarketMode : : CREATURE_EXP )
return ;
int stackCount = 0 ;
for ( int i = 0 ; i < GameConstants : : ARMY_SIZE ; i + + )
if ( hero - > getStackCount ( SlotID ( i ) ) > sacrificedUnits [ i ] )
stackCount + + ;
slider - > setAmount ( hero - > getStackCount ( SlotID ( hLeft - > serial ) ) - ( stackCount = = 1 ) ) ;
2014-08-03 17:31:56 +03:00
slider - > block ( ! slider - > getAmount ( ) ) ;
2023-05-30 17:10:22 +02:00
slider - > scrollTo ( sacrificedUnits [ hLeft - > serial ] ) ;
2014-08-03 17:31:56 +03:00
max - > block ( ! slider - > getAmount ( ) ) ;
2017-08-01 17:17:46 +02:00
selectOppositeItem ( side ) ;
2014-07-13 16:31:00 +03:00
readyToTrade = true ;
redraw ( ) ;
}
2017-08-01 17:17:46 +02:00
void CAltarWindow : : selectOppositeItem ( bool side )
{
bool oppositeSide = ! side ;
int pos = vstd : : find_pos ( items [ side ] , side ? hLeft : hRight ) ;
int oppositePos = vstd : : find_pos ( items [ oppositeSide ] , oppositeSide ? hLeft : hRight ) ;
if ( pos > = 0 & & pos ! = oppositePos )
{
if ( oppositeSide )
hLeft = items [ oppositeSide ] [ pos ] ;
else
hRight = items [ oppositeSide ] [ pos ] ;
selectionChanged ( oppositeSide ) ;
}
}
2014-07-13 16:31:00 +03:00
void CAltarWindow : : mimicCres ( )
{
2018-04-07 13:34:11 +02:00
OBJECT_CONSTRUCTION_CUSTOM_CAPTURING ( 255 - DISPOSE ) ;
2014-07-13 16:31:00 +03:00
std : : vector < Rect > positions ;
getPositionsFor ( positions , false , CREATURE ) ;
2018-04-07 13:34:11 +02:00
for ( auto item : items [ 1 ] )
2014-07-13 16:31:00 +03:00
{
2018-04-07 13:34:11 +02:00
auto hlp = std : : make_shared < CTradeableItem > ( positions [ item - > serial ] . topLeft ( ) , CREATURE_PLACEHOLDER , item - > id , false , item - > serial ) ;
hlp - > pos = positions [ item - > serial ] + this - > pos . topLeft ( ) ;
2014-07-13 16:31:00 +03:00
items [ 0 ] . push_back ( hlp ) ;
}
}
Point CAltarWindow : : selectionOffset ( bool Left ) const
{
if ( Left )
return Point ( 150 , 421 ) ;
else
return Point ( 396 , 421 ) ;
}
std : : string CAltarWindow : : selectionSubtitle ( bool Left ) const
{
if ( Left & & slider & & hLeft )
2023-03-09 15:36:46 +02:00
return std : : to_string ( slider - > getValue ( ) ) ;
2014-07-13 16:31:00 +03:00
else if ( ! Left & & hRight )
return hRight - > subtitle ;
else
return " " ;
}
void CAltarWindow : : artifactsChanged ( bool left )
{
}
void CAltarWindow : : garrisonChanged ( )
{
if ( mode ! = EMarketMode : : CREATURE_EXP )
return ;
2018-04-07 13:34:11 +02:00
std : : set < std : : shared_ptr < CTradeableItem > > empty ;
2014-07-13 16:31:00 +03:00
getEmptySlots ( empty ) ;
2014-12-26 00:18:58 +02:00
removeItems ( empty ) ;
2014-07-13 16:31:00 +03:00
initSubs ( true ) ;
getExpValues ( ) ;
}
void CAltarWindow : : getExpValues ( )
{
int dump ;
2018-04-07 13:34:11 +02:00
for ( auto item : items [ 1 ] )
{
if ( item - > id > = 0 )
market - > getOffer ( item - > id , 0 , dump , expPerUnit [ item - > serial ] , EMarketMode : : CREATURE_EXP ) ;
}
2014-07-13 16:31:00 +03:00
}
void CAltarWindow : : calcTotalExp ( )
{
int val = 0 ;
if ( mode = = EMarketMode : : CREATURE_EXP )
{
for ( int i = 0 ; i < sacrificedUnits . size ( ) ; i + + )
{
val + = expPerUnit [ i ] * sacrificedUnits [ i ] ;
}
}
else
{
2023-04-23 13:33:47 +02:00
auto artifactsOfHero = std : : dynamic_pointer_cast < CArtifactsOfHeroAltar > ( arts ) ;
for ( const CArtifactInstance * art : artifactsOfHero - > artifactsOnAltar )
2014-07-13 16:31:00 +03:00
{
int dmp , valOfArt ;
2023-01-02 15:58:56 +02:00
market - > getOffer ( art - > artType - > getId ( ) , 0 , dmp , valOfArt , mode ) ;
2014-07-13 16:31:00 +03:00
val + = valOfArt ; //WAS val += valOfArt * arts->artifactsOnAltar.count(*i);
}
}
2020-10-01 10:38:06 +02:00
val = static_cast < int > ( hero - > calculateXp ( val ) ) ;
2023-03-09 15:36:46 +02:00
expOnAltar - > setText ( std : : to_string ( val ) ) ;
2014-07-13 16:31:00 +03:00
}
void CAltarWindow : : setExpToLevel ( )
{
2023-03-09 15:36:46 +02:00
expToLevel - > setText ( std : : to_string ( CGI - > heroh - > reqExp ( CGI - > heroh - > level ( hero - > exp ) + 1 ) - hero - > exp ) ) ;
2014-07-13 16:31:00 +03:00
}
void CAltarWindow : : blockTrade ( )
{
hLeft = hRight = nullptr ;
readyToTrade = false ;
if ( slider )
{
slider - > block ( true ) ;
max - > block ( true ) ;
}
deal - > block ( true ) ;
}
2018-04-07 13:34:11 +02:00
void CAltarWindow : : updateRight ( std : : shared_ptr < CTradeableItem > toUpdate )
2014-07-13 16:31:00 +03:00
{
int val = sacrificedUnits [ toUpdate - > serial ] ;
toUpdate - > setType ( val ? CREATURE : CREATURE_PLACEHOLDER ) ;
2023-03-09 15:36:46 +02:00
toUpdate - > subtitle = val ? boost : : str ( boost : : format ( CGI - > generaltexth - > allTexts [ 122 ] ) % std : : to_string ( hero - > calculateXp ( val * expPerUnit [ toUpdate - > serial ] ) ) ) : " " ; //%s exp
2014-07-13 16:31:00 +03:00
}
int CAltarWindow : : firstFreeSlot ( )
{
int ret = - 1 ;
while ( items [ 0 ] [ + + ret ] - > id > = 0 & & ret + 1 < items [ 0 ] . size ( ) ) ;
2014-12-25 05:17:26 +02:00
return items [ 0 ] [ ret ] - > id = = - 1 ? ret : - 1 ;
2014-07-13 16:31:00 +03:00
}
void CAltarWindow : : SacrificeBackpack ( )
{
2023-07-06 21:14:12 +02:00
while ( ! arts - > visibleArtSet . artifactsInBackpack . empty ( ) )
2014-07-13 16:31:00 +03:00
{
2023-07-06 21:14:12 +02:00
if ( ! putOnAltar ( nullptr , arts - > visibleArtSet . artifactsInBackpack [ 0 ] . artifact ) )
2023-04-23 13:33:47 +02:00
break ;
} ;
2014-07-13 16:31:00 +03:00
calcTotalExp ( ) ;
}
void CAltarWindow : : artifactPicked ( )
{
redraw ( ) ;
}
2023-06-02 15:42:18 +02:00
void CAltarWindow : : showAll ( Canvas & to )
2014-07-13 16:31:00 +03:00
{
CTradeWindow : : showAll ( to ) ;
2023-04-23 13:33:47 +02:00
if ( mode = = EMarketMode : : ARTIFACT_EXP & & arts )
2014-07-13 16:31:00 +03:00
{
2023-04-23 13:33:47 +02:00
if ( auto pickedArt = arts - > getPickedArtifact ( ) )
{
artIcon - > setFrame ( pickedArt - > artType - > getIconIndex ( ) ) ;
artIcon - > showAll ( to ) ;
2014-07-13 16:31:00 +03:00
2023-04-23 13:33:47 +02:00
int dmp , val ;
market - > getOffer ( pickedArt - > getTypeId ( ) , 0 , dmp , val , EMarketMode : : ARTIFACT_EXP ) ;
val = static_cast < int > ( hero - > calculateXp ( val ) ) ;
2023-06-02 15:42:18 +02:00
to . drawText ( Point ( 304 , 498 ) , FONT_SMALL , Colors : : WHITE , ETextAlignment : : CENTER , std : : to_string ( val ) ) ;
2023-04-23 13:33:47 +02:00
}
2014-07-13 16:31:00 +03:00
}
}
2018-04-07 13:34:11 +02:00
bool CAltarWindow : : putOnAltar ( std : : shared_ptr < CTradeableItem > altarSlot , const CArtifactInstance * art )
2014-07-13 16:31:00 +03:00
{
2014-12-24 19:48:37 +02:00
if ( ! art - > artType - > isTradable ( ) ) //special art
2014-07-13 16:31:00 +03:00
{
2017-08-10 18:39:27 +02:00
logGlobal - > warn ( " Cannot put special artifact on altar! " ) ;
2014-07-13 16:31:00 +03:00
return false ;
}
2014-12-26 00:42:50 +02:00
if ( ! altarSlot | | altarSlot - > id ! = - 1 )
2014-07-13 16:31:00 +03:00
{
int slotIndex = firstFreeSlot ( ) ;
if ( slotIndex < 0 )
{
2017-08-10 18:39:27 +02:00
logGlobal - > warn ( " No free slots on altar! " ) ;
2014-07-13 16:31:00 +03:00
return false ;
}
altarSlot = items [ 0 ] [ slotIndex ] ;
}
int dmp , val ;
2023-01-02 15:58:56 +02:00
market - > getOffer ( art - > artType - > getId ( ) , 0 , dmp , val , EMarketMode : : ARTIFACT_EXP ) ;
2020-10-01 10:38:06 +02:00
val = static_cast < int > ( hero - > calculateXp ( val ) ) ;
2014-07-13 16:31:00 +03:00
2023-07-06 20:37:18 +02:00
arts - > artifactsOnAltar . insert ( art ) ;
arts - > deleteFromVisible ( art ) ;
2014-07-13 16:31:00 +03:00
altarSlot - > setArtInstance ( art ) ;
2023-03-09 15:36:46 +02:00
altarSlot - > subtitle = std : : to_string ( val ) ;
2014-07-13 16:31:00 +03:00
deal - > block ( false ) ;
return true ;
}
2023-04-23 13:33:47 +02:00
void CAltarWindow : : moveArtToAltar ( std : : shared_ptr < CTradeableItem > altarSlot , const CArtifactInstance * art )
2014-07-13 16:31:00 +03:00
{
if ( putOnAltar ( altarSlot , art ) )
{
2023-04-23 13:33:47 +02:00
CCS - > curh - > dragAndDropCursor ( nullptr ) ;
arts - > unmarkSlots ( ) ;
2014-07-13 16:31:00 +03:00
}
}