2014-03-17 22:51:07 +03:00
/*
* CArtHandler . cpp , part of VCMI engine
*
* Authors : listed in file AUTHORS in main folder
*
* License : GNU General Public License v2 .0 or later
* Full text of license available in license . txt file , in main folder
*
*/
2011-12-14 00:23:17 +03:00
# include "StdInc.h"
2007-06-07 23:16:19 +03:00
# include "CArtHandler.h"
2011-12-14 00:23:17 +03:00
2013-07-28 17:49:50 +03:00
# include "filesystem/Filesystem.h"
2008-11-30 02:15:38 +02:00
# include "CGeneralTextHandler.h"
2012-08-01 15:02:54 +03:00
# include "VCMI_Lib.h"
2012-08-24 12:37:52 +03:00
# include "CModHandler.h"
2010-12-17 20:47:07 +02:00
# include "CSpellHandler.h"
2014-06-05 19:52:14 +03:00
# include "mapObjects/MapObjects.h"
2014-01-16 23:24:06 +03:00
# include "NetPacksBase.h"
2013-01-06 22:30:12 +03:00
# include "GameConstants.h"
2014-03-17 22:51:07 +03:00
# include "CRandomGenerator.h"
2010-12-26 16:34:11 +02:00
2014-06-05 19:52:14 +03:00
# include "mapObjects/CObjectClassesHandler.h"
2008-06-13 11:16:51 +03:00
using namespace boost : : assign ;
2009-04-04 01:34:31 +03:00
2013-03-12 17:56:23 +03:00
// Note: list must match entries in ArtTraits.txt
# define ART_POS_LIST \
ART_POS ( SPELLBOOK ) \
ART_POS ( MACH4 ) \
ART_POS ( MACH3 ) \
ART_POS ( MACH2 ) \
ART_POS ( MACH1 ) \
ART_POS ( MISC5 ) \
ART_POS ( MISC4 ) \
ART_POS ( MISC3 ) \
ART_POS ( MISC2 ) \
ART_POS ( MISC1 ) \
ART_POS ( FEET ) \
ART_POS ( LEFT_RING ) \
ART_POS ( RIGHT_RING ) \
ART_POS ( TORSO ) \
ART_POS ( LEFT_HAND ) \
ART_POS ( RIGHT_HAND ) \
ART_POS ( NECK ) \
ART_POS ( SHOULDERS ) \
ART_POS ( HEAD ) ;
2012-12-10 16:55:54 +03:00
2009-04-04 01:34:31 +03:00
const std : : string & CArtifact : : Name ( ) const
{
2012-12-06 22:03:47 +03:00
return name ;
2009-04-04 01:34:31 +03:00
}
const std : : string & CArtifact : : Description ( ) const
{
2012-12-06 22:03:47 +03:00
return description ;
}
const std : : string & CArtifact : : EventText ( ) const
{
return eventText ;
2009-04-04 01:34:31 +03:00
}
2009-12-30 17:33:28 +02:00
2010-02-09 04:17:38 +02:00
bool CArtifact : : isBig ( ) const
2009-12-30 17:33:28 +02:00
{
return VLC - > arth - > isBigArtifact ( id ) ;
}
2010-07-20 21:34:32 +03:00
CArtifact : : CArtifact ( )
2010-05-09 22:10:59 +03:00
{
2011-07-13 21:39:02 +03:00
setNodeType ( ARTIFACT ) ;
2012-12-14 11:37:46 +03:00
possibleSlots [ ArtBearer : : HERO ] ; //we want to generate map entry even if it will be empty
possibleSlots [ ArtBearer : : CREATURE ] ; //we want to generate map entry even if it will be empty
possibleSlots [ ArtBearer : : COMMANDER ] ;
2010-05-09 22:10:59 +03:00
}
2010-07-20 21:34:32 +03:00
CArtifact : : ~ CArtifact ( )
2010-05-09 22:10:59 +03:00
{
}
2010-07-23 15:02:15 +03:00
int CArtifact : : getArtClassSerial ( ) const
{
if ( id = = 1 )
return 4 ;
switch ( aClass )
{
case ART_TREASURE :
return 0 ;
case ART_MINOR :
return 1 ;
case ART_MAJOR :
return 2 ;
case ART_RELIC :
return 3 ;
case ART_SPECIAL :
return 5 ;
}
return - 1 ;
}
2010-12-17 20:47:07 +02:00
std : : string CArtifact : : nodeName ( ) const
{
return " Artifact: " + Name ( ) ;
}
2010-11-10 02:06:25 +02:00
2012-12-13 17:27:33 +03:00
void CArtifact : : addNewBonus ( Bonus * b )
{
b - > source = Bonus : : ARTIFACT ;
b - > duration = Bonus : : PERMANENT ;
b - > description = name ;
CBonusSystemNode : : addNewBonus ( b ) ;
}
2012-07-16 19:18:02 +03:00
void CGrowingArtifact : : levelUpArtifact ( CArtifactInstance * art )
{
Bonus b ;
b . type = Bonus : : LEVEL_COUNTER ;
b . val = 1 ;
b . duration = Bonus : : COMMANDER_KILLED ;
art - > accumulateBonus ( b ) ;
2013-06-29 16:05:48 +03:00
for ( auto bonus : bonusesPerLevel )
2012-07-16 19:18:02 +03:00
{
if ( art - > valOfBonuses ( Bonus : : LEVEL_COUNTER ) % bonus . first = = 0 ) //every n levels
{
art - > accumulateBonus ( bonus . second ) ;
}
}
2013-06-29 16:05:48 +03:00
for ( auto bonus : thresholdBonuses )
2012-07-16 19:18:02 +03:00
{
if ( art - > valOfBonuses ( Bonus : : LEVEL_COUNTER ) = = bonus . first ) //every n levels
{
art - > addNewBonus ( & bonus . second ) ;
}
}
}
2008-06-17 20:48:32 +03:00
CArtHandler : : CArtHandler ( )
{
2013-01-03 15:19:20 +03:00
//VLC->arth = this;
2009-12-02 01:19:43 +02:00
// War machines are the default big artifacts.
2013-02-11 02:24:57 +03:00
for ( ArtifactID i = ArtifactID : : CATAPULT ; i < = ArtifactID : : FIRST_AID_TENT ; i . advance ( 1 ) )
2009-12-02 01:19:43 +02:00
bigArtifacts . insert ( i ) ;
2008-06-17 20:48:32 +03:00
}
2010-02-16 16:39:56 +02:00
CArtHandler : : ~ CArtHandler ( )
{
2013-06-29 16:05:48 +03:00
for ( CArtifact * art : artifacts )
2013-04-21 19:38:31 +03:00
delete art ;
2010-02-16 16:39:56 +02:00
}
2013-04-21 15:49:26 +03:00
std : : vector < JsonNode > CArtHandler : : loadLegacyData ( size_t dataSize )
2007-06-07 23:16:19 +03:00
{
2013-04-21 15:49:26 +03:00
artifacts . resize ( dataSize ) ;
std : : vector < JsonNode > h3Data ;
h3Data . reserve ( dataSize ) ;
2013-03-02 19:55:51 +03:00
2013-03-12 17:56:23 +03:00
# define ART_POS(x) ( #x)
const std : : vector < std : : string > artSlots = boost : : assign : : list_of ART_POS_LIST ;
# undef ART_POS
2013-03-02 19:55:51 +03:00
2013-03-12 17:56:23 +03:00
static std : : map < char , std : : string > classes =
map_list_of ( ' S ' , " SPECIAL " ) ( ' T ' , " TREASURE " ) ( ' N ' , " MINOR " ) ( ' J ' , " MAJOR " ) ( ' R ' , " RELIC " ) ;
2012-08-01 15:02:54 +03:00
2012-08-25 11:44:51 +03:00
CLegacyConfigParser parser ( " DATA/ARTRAITS.TXT " ) ;
2012-12-06 22:03:47 +03:00
CLegacyConfigParser events ( " DATA/ARTEVENT.TXT " ) ;
2012-08-25 11:44:51 +03:00
parser . endLine ( ) ; // header
parser . endLine ( ) ;
2013-04-21 15:49:26 +03:00
for ( size_t i = 0 ; i < dataSize ; i + + )
2007-06-07 23:16:19 +03:00
{
2013-03-12 17:56:23 +03:00
JsonNode artData ;
2012-08-25 11:44:51 +03:00
2013-03-12 17:56:23 +03:00
artData [ " text " ] [ " name " ] . String ( ) = parser . readString ( ) ;
artData [ " text " ] [ " event " ] . String ( ) = events . readString ( ) ;
artData [ " value " ] . Float ( ) = parser . readNumber ( ) ;
2012-08-25 11:44:51 +03:00
2013-06-29 16:05:48 +03:00
for ( auto & artSlot : artSlots )
2007-06-07 23:16:19 +03:00
{
2012-08-25 11:44:51 +03:00
if ( parser . readString ( ) = = " x " )
2012-07-16 19:18:02 +03:00
{
2013-03-12 17:56:23 +03:00
artData [ " slot " ] . Vector ( ) . push_back ( JsonNode ( ) ) ;
2013-06-29 16:05:48 +03:00
artData [ " slot " ] . Vector ( ) . back ( ) . String ( ) = artSlot ;
2012-07-16 19:18:02 +03:00
}
}
2013-03-12 17:56:23 +03:00
artData [ " class " ] . String ( ) = classes [ parser . readString ( ) [ 0 ] ] ;
artData [ " text " ] [ " description " ] . String ( ) = parser . readString ( ) ;
parser . endLine ( ) ;
events . endLine ( ) ;
h3Data . push_back ( artData ) ;
2012-07-16 19:18:02 +03:00
}
2013-04-21 15:49:26 +03:00
return h3Data ;
}
2012-07-16 19:18:02 +03:00
2013-04-21 15:49:26 +03:00
void CArtHandler : : loadObject ( std : : string scope , std : : string name , const JsonNode & data )
{
auto object = loadFromJson ( data ) ;
object - > id = ArtifactID ( artifacts . size ( ) ) ;
2014-01-30 14:08:37 +03:00
object - > iconIndex = object - > id + 5 ;
2013-03-02 19:55:51 +03:00
2013-04-21 15:49:26 +03:00
artifacts . push_back ( object ) ;
2013-03-12 17:56:23 +03:00
2013-04-21 15:49:26 +03:00
VLC - > modh - > identifiers . registerObject ( scope , " artifact " , name , object - > id ) ;
2007-06-08 17:58:04 +03:00
}
2008-08-30 00:41:32 +03:00
2013-04-21 15:49:26 +03:00
void CArtHandler : : loadObject ( std : : string scope , std : : string name , const JsonNode & data , size_t index )
2012-12-10 16:55:54 +03:00
{
2013-04-21 15:49:26 +03:00
auto object = loadFromJson ( data ) ;
object - > id = ArtifactID ( index ) ;
2014-01-30 14:08:37 +03:00
object - > iconIndex = object - > id ;
2013-04-21 15:49:26 +03:00
assert ( artifacts [ index ] = = nullptr ) ; // ensure that this id was not loaded before
artifacts [ index ] = object ;
2012-12-10 16:55:54 +03:00
2013-04-21 15:49:26 +03:00
VLC - > modh - > identifiers . registerObject ( scope , " artifact " , name , object - > id ) ;
2012-12-10 16:55:54 +03:00
}
2013-04-21 15:49:26 +03:00
CArtifact * CArtHandler : : loadFromJson ( const JsonNode & node )
2012-12-10 16:55:54 +03:00
{
2013-03-12 17:56:23 +03:00
CArtifact * art ;
if ( ! VLC - > modh - > modules . COMMANDERS | | node [ " growing " ] . isNull ( ) )
art = new CArtifact ( ) ;
else
{
2013-06-29 16:05:48 +03:00
auto growing = new CGrowingArtifact ( ) ;
2013-03-12 17:56:23 +03:00
loadGrowingArt ( growing , node ) ;
art = growing ;
}
2012-12-10 16:55:54 +03:00
const JsonNode & text = node [ " text " ] ;
2013-03-02 19:55:51 +03:00
art - > name = text [ " name " ] . String ( ) ;
art - > description = text [ " description " ] . String ( ) ;
art - > eventText = text [ " event " ] . String ( ) ;
2012-12-10 16:55:54 +03:00
2012-12-13 18:38:04 +03:00
const JsonNode & graphics = node [ " graphics " ] ;
2012-12-13 17:27:33 +03:00
art - > image = graphics [ " image " ] . String ( ) ;
2013-03-02 19:55:51 +03:00
2013-04-02 20:06:43 +03:00
if ( ! graphics [ " large " ] . isNull ( ) )
art - > large = graphics [ " large " ] . String ( ) ;
else
2013-03-02 19:55:51 +03:00
art - > large = art - > image ;
2012-12-16 14:35:14 +03:00
art - > advMapDef = graphics [ " map " ] . String ( ) ;
2012-12-10 16:55:54 +03:00
art - > price = node [ " value " ] . Float ( ) ;
2013-03-12 17:56:23 +03:00
loadSlots ( art , node ) ;
loadClass ( art , node ) ;
loadType ( art , node ) ;
loadComponents ( art , node ) ;
2013-06-29 16:05:48 +03:00
for ( auto b : node [ " bonuses " ] . Vector ( ) )
2013-03-12 17:56:23 +03:00
{
auto bonus = JsonUtils : : parseBonus ( b ) ;
2013-07-21 17:19:29 +03:00
art - > addNewBonus ( bonus ) ;
2013-03-12 17:56:23 +03:00
}
return art ;
}
2014-06-22 13:39:40 +03:00
ArtifactPosition CArtHandler : : stringToSlot ( std : : string slotName )
2013-03-12 17:56:23 +03:00
{
# define ART_POS(x) ( #x, ArtifactPosition::x )
static const std : : map < std : : string , ArtifactPosition > artifactPositionMap = boost : : assign : : map_list_of ART_POS_LIST ;
# undef ART_POS
2014-06-22 13:39:40 +03:00
auto it = artifactPositionMap . find ( slotName ) ;
if ( it ! = artifactPositionMap . end ( ) )
return it - > second ;
logGlobal - > warnStream ( ) < < " Warning! Artifact slot " < < slotName < < " not recognized! " ;
return ArtifactPosition : : PRE_FIRST ;
}
2013-03-12 17:56:23 +03:00
2014-06-22 13:39:40 +03:00
void CArtHandler : : addSlot ( CArtifact * art , const std : : string & slotID )
{
2013-03-12 17:56:23 +03:00
if ( slotID = = " MISC " )
2012-12-14 11:37:46 +03:00
{
2013-03-12 17:56:23 +03:00
art - > possibleSlots [ ArtBearer : : HERO ] + = ArtifactPosition : : MISC1 , ArtifactPosition : : MISC2 , ArtifactPosition : : MISC3 , ArtifactPosition : : MISC4 , ArtifactPosition : : MISC5 ;
}
else if ( slotID = = " RING " )
{
art - > possibleSlots [ ArtBearer : : HERO ] + = ArtifactPosition : : LEFT_RING , ArtifactPosition : : RIGHT_RING ;
}
else
{
2014-06-22 13:39:40 +03:00
auto slot = stringToSlot ( slotID ) ;
if ( slot ! = ArtifactPosition : : PRE_FIRST )
2013-03-12 17:56:23 +03:00
art - > possibleSlots [ ArtBearer : : HERO ] . push_back ( slot ) ;
2012-12-14 11:37:46 +03:00
}
2013-03-12 17:56:23 +03:00
}
2013-02-05 00:58:42 +03:00
2013-03-12 17:56:23 +03:00
void CArtHandler : : loadSlots ( CArtifact * art , const JsonNode & node )
{
2013-03-02 19:55:51 +03:00
if ( ! node [ " slot " ] . isNull ( ) ) //we assume non-hero slots are irrelevant?
2012-12-10 17:28:27 +03:00
{
2013-03-12 17:56:23 +03:00
if ( node [ " slot " ] . getType ( ) = = JsonNode : : DATA_STRING )
addSlot ( art , node [ " slot " ] . String ( ) ) ;
2012-12-10 16:55:54 +03:00
else
2012-12-14 11:37:46 +03:00
{
2013-06-29 16:05:48 +03:00
for ( const JsonNode & slot : node [ " slot " ] . Vector ( ) )
2013-03-12 17:56:23 +03:00
addSlot ( art , slot . String ( ) ) ;
2012-12-14 11:37:46 +03:00
}
2012-12-10 16:55:54 +03:00
}
2013-03-02 19:55:51 +03:00
}
2014-06-22 13:39:40 +03:00
CArtifact : : EartClass CArtHandler : : stringToClass ( std : : string className )
2013-03-02 19:55:51 +03:00
{
2013-03-12 17:56:23 +03:00
static const std : : map < std : : string , CArtifact : : EartClass > artifactClassMap = boost : : assign : : map_list_of
( " TREASURE " , CArtifact : : ART_TREASURE )
( " MINOR " , CArtifact : : ART_MINOR )
( " MAJOR " , CArtifact : : ART_MAJOR )
( " RELIC " , CArtifact : : ART_RELIC )
( " SPECIAL " , CArtifact : : ART_SPECIAL ) ;
2014-06-22 13:39:40 +03:00
auto it = artifactClassMap . find ( className ) ;
2013-03-12 17:56:23 +03:00
if ( it ! = artifactClassMap . end ( ) )
2014-06-22 13:39:40 +03:00
return it - > second ;
logGlobal - > warnStream ( ) < < " Warning! Artifact rarity " < < className < < " not recognized! " ;
return CArtifact : : ART_SPECIAL ;
}
void CArtHandler : : loadClass ( CArtifact * art , const JsonNode & node )
{
art - > aClass = stringToClass ( node [ " class " ] . String ( ) ) ;
2013-03-12 17:56:23 +03:00
}
void CArtHandler : : loadType ( CArtifact * art , const JsonNode & node )
{
# define ART_BEARER(x) ( #x, ArtBearer::x )
static const std : : map < std : : string , int > artifactBearerMap = boost : : assign : : map_list_of ART_BEARER_LIST ;
# undef ART_BEARER
2013-06-29 16:05:48 +03:00
for ( const JsonNode & b : node [ " type " ] . Vector ( ) )
2012-12-10 16:55:54 +03:00
{
2013-03-02 19:55:51 +03:00
auto it = artifactBearerMap . find ( b . String ( ) ) ;
if ( it ! = artifactBearerMap . end ( ) )
{
int bearerType = it - > second ;
switch ( bearerType )
{
case ArtBearer : : HERO : //TODO: allow arts having several possible bearers
break ;
case ArtBearer : : COMMANDER :
makeItCommanderArt ( art ) ; //original artifacts should have only one bearer type
break ;
case ArtBearer : : CREATURE :
makeItCreatureArt ( art ) ;
break ;
}
}
else
2013-04-09 17:31:36 +03:00
logGlobal - > warnStream ( ) < < " Warning! Artifact type " < < b . String ( ) < < " not recognized! " ;
2012-12-10 16:55:54 +03:00
}
2013-03-12 17:56:23 +03:00
}
2012-12-10 16:55:54 +03:00
2013-03-12 17:56:23 +03:00
void CArtHandler : : loadComponents ( CArtifact * art , const JsonNode & node )
{
if ( ! node [ " components " ] . isNull ( ) )
2013-03-02 19:55:51 +03:00
{
2013-03-02 21:41:25 +03:00
art - > constituents . reset ( new std : : vector < CArtifact * > ( ) ) ;
2013-06-29 16:05:48 +03:00
for ( auto component : node [ " components " ] . Vector ( ) )
2013-03-02 19:55:51 +03:00
{
2013-04-25 17:03:35 +03:00
VLC - > modh - > identifiers . requestIdentifier ( " artifact " , component , [ = ] ( si32 id )
2013-03-02 19:55:51 +03:00
{
// when this code is called both combinational art as well as component are loaded
// so it is safe to access any of them
2013-03-02 21:41:25 +03:00
art - > constituents - > push_back ( VLC - > arth - > artifacts [ id ] ) ;
VLC - > arth - > artifacts [ id ] - > constituentOf . push_back ( art ) ;
2013-03-02 19:55:51 +03:00
} ) ;
}
}
2012-12-10 16:55:54 +03:00
}
2013-03-12 17:56:23 +03:00
void CArtHandler : : loadGrowingArt ( CGrowingArtifact * art , const JsonNode & node )
{
2013-06-29 16:05:48 +03:00
for ( auto b : node [ " growing " ] [ " bonusesPerLevel " ] . Vector ( ) )
2013-03-12 17:56:23 +03:00
{
2013-04-11 22:24:14 +03:00
art - > bonusesPerLevel . push_back ( std : : pair < ui16 , Bonus > ( b [ " level " ] . Float ( ) , * JsonUtils : : parseBonus ( b [ " bonus " ] ) ) ) ;
2013-03-12 17:56:23 +03:00
}
2013-06-29 16:05:48 +03:00
for ( auto b : node [ " growing " ] [ " thresholdBonuses " ] . Vector ( ) )
2013-03-12 17:56:23 +03:00
{
2013-04-11 22:24:14 +03:00
art - > thresholdBonuses . push_back ( std : : pair < ui16 , Bonus > ( b [ " level " ] . Float ( ) , * JsonUtils : : parseBonus ( b [ " bonus " ] ) ) ) ;
2013-03-12 17:56:23 +03:00
}
}
2013-12-19 17:35:49 +03:00
//TODO: use bimap
2013-02-11 02:24:57 +03:00
ArtifactID CArtHandler : : creatureToMachineID ( CreatureID id )
2008-08-30 00:41:32 +03:00
{
2013-02-07 20:34:50 +03:00
switch ( id )
2008-08-30 00:41:32 +03:00
{
2013-12-19 17:35:49 +03:00
case CreatureID : : CATAPULT : //Catapult
return ArtifactID : : CATAPULT ;
2013-02-07 20:34:50 +03:00
break ;
2013-12-19 17:35:49 +03:00
case CreatureID : : BALLISTA : //Ballista
return ArtifactID : : BALLISTA ;
break ;
case CreatureID : : FIRST_AID_TENT : //First Aid tent
return ArtifactID : : FIRST_AID_TENT ;
break ;
case CreatureID : : AMMO_CART : //Ammo cart
return ArtifactID : : AMMO_CART ;
2013-02-07 20:34:50 +03:00
break ;
2008-08-30 00:41:32 +03:00
}
2013-12-19 17:35:49 +03:00
return ArtifactID : : NONE ; //this creature is not artifact
2013-02-07 20:34:50 +03:00
}
2013-02-11 02:24:57 +03:00
CreatureID CArtHandler : : machineIDToCreature ( ArtifactID id )
2013-02-07 20:34:50 +03:00
{
switch ( id )
2008-08-30 00:41:32 +03:00
{
2013-12-19 17:35:49 +03:00
case ArtifactID : : CATAPULT :
return CreatureID : : CATAPULT ;
break ;
case ArtifactID : : BALLISTA :
return CreatureID : : BALLISTA ;
break ;
case ArtifactID : : FIRST_AID_TENT :
return CreatureID : : FIRST_AID_TENT ;
2013-02-07 20:34:50 +03:00
break ;
2013-12-19 17:35:49 +03:00
case ArtifactID : : AMMO_CART :
return CreatureID : : AMMO_CART ;
2013-02-07 20:34:50 +03:00
break ;
2008-08-30 00:41:32 +03:00
}
2013-12-19 17:35:49 +03:00
return CreatureID : : NONE ; //this artifact is not a creature
2008-11-28 03:36:34 +02:00
}
2014-06-22 13:39:40 +03:00
ArtifactID CArtHandler : : pickRandomArtifact ( CRandomGenerator & rand , int flags , std : : function < bool ( ArtifactID ) > accepts )
2010-06-28 08:07:21 +03:00
{
2013-02-19 01:37:22 +03:00
auto getAllowedArts = [ & ] ( std : : vector < ConstTransitivePtr < CArtifact > > & out , std : : vector < CArtifact * > * arts , CArtifact : : EartClass flag )
2010-06-28 08:07:21 +03:00
{
2013-02-13 01:24:48 +03:00
if ( arts - > empty ( ) ) //restock available arts
2013-02-19 01:37:22 +03:00
fillList ( * arts , flag ) ;
2008-11-30 02:15:38 +02:00
2013-06-29 16:05:48 +03:00
for ( auto & arts_i : * arts )
2013-02-13 01:24:48 +03:00
{
2014-06-22 13:39:40 +03:00
if ( accepts ( arts_i - > id ) )
{
CArtifact * art = arts_i ;
out . push_back ( art ) ;
}
2013-02-13 01:24:48 +03:00
}
} ;
auto getAllowed = [ & ] ( std : : vector < ConstTransitivePtr < CArtifact > > & out )
2010-06-28 08:07:21 +03:00
{
2013-02-13 01:24:48 +03:00
if ( flags & CArtifact : : ART_TREASURE )
getAllowedArts ( out , & treasures , CArtifact : : ART_TREASURE ) ;
if ( flags & CArtifact : : ART_MINOR )
getAllowedArts ( out , & minors , CArtifact : : ART_MINOR ) ;
if ( flags & CArtifact : : ART_MAJOR )
getAllowedArts ( out , & majors , CArtifact : : ART_MAJOR ) ;
if ( flags & CArtifact : : ART_RELIC )
getAllowedArts ( out , & relics , CArtifact : : ART_RELIC ) ;
if ( ! out . size ( ) ) //no artifact of specified rarity, we need to take another one
{
getAllowedArts ( out , & treasures , CArtifact : : ART_TREASURE ) ;
getAllowedArts ( out , & minors , CArtifact : : ART_MINOR ) ;
getAllowedArts ( out , & majors , CArtifact : : ART_MAJOR ) ;
getAllowedArts ( out , & relics , CArtifact : : ART_RELIC ) ;
}
if ( ! out . size ( ) ) //no arts are available at all
{
out . resize ( 64 ) ;
std : : fill_n ( out . begin ( ) , 64 , artifacts [ 2 ] ) ; //Give Grail - this can't be banned (hopefully)
}
} ;
std : : vector < ConstTransitivePtr < CArtifact > > out ;
getAllowed ( out ) ;
2014-03-17 22:51:07 +03:00
ArtifactID artID = ( * RandomGeneratorUtil : : nextItem ( out , rand ) ) - > id ;
erasePickedArt ( artID ) ;
2013-02-13 01:24:48 +03:00
return artID ;
2010-06-28 08:07:21 +03:00
}
2012-08-26 12:07:48 +03:00
2014-06-22 13:39:40 +03:00
ArtifactID CArtHandler : : pickRandomArtifact ( CRandomGenerator & rand , std : : function < bool ( ArtifactID ) > accepts )
{
return pickRandomArtifact ( rand , 0xff , accepts ) ;
}
ArtifactID CArtHandler : : pickRandomArtifact ( CRandomGenerator & rand , int flags )
{
return pickRandomArtifact ( rand , flags , [ ] ( ArtifactID ) { return true ; } ) ;
}
2013-02-02 01:04:25 +03:00
Bonus * createBonus ( Bonus : : BonusType type , int val , int subtype , Bonus : : ValueType valType , shared_ptr < ILimiter > limiter = shared_ptr < ILimiter > ( ) , int additionalInfo = 0 )
2008-11-30 02:15:38 +02:00
{
2013-06-29 16:05:48 +03:00
auto added = new Bonus ( Bonus : : PERMANENT , type , Bonus : : ARTIFACT , val , - 1 , subtype ) ;
2012-04-17 11:46:09 +03:00
added - > additionalInfo = additionalInfo ;
2010-11-20 02:03:31 +02:00
added - > valType = valType ;
2012-08-26 12:07:48 +03:00
added - > limiter = limiter ;
return added ;
2011-08-26 23:32:05 +03:00
}
2012-11-02 23:08:37 +03:00
Bonus * createBonus ( Bonus : : BonusType type , int val , int subtype , shared_ptr < IPropagator > propagator = shared_ptr < IPropagator > ( ) , int additionalInfo = 0 )
2011-08-26 23:32:05 +03:00
{
2013-06-29 16:05:48 +03:00
auto added = new Bonus ( Bonus : : PERMANENT , type , Bonus : : ARTIFACT , val , - 1 , subtype ) ;
2012-04-17 11:46:09 +03:00
added - > additionalInfo = additionalInfo ;
2011-08-26 23:32:05 +03:00
added - > valType = Bonus : : BASE_NUMBER ;
2012-08-26 12:07:48 +03:00
added - > propagator = propagator ;
return added ;
}
2013-02-11 02:24:57 +03:00
void CArtHandler : : giveArtBonus ( ArtifactID aid , Bonus : : BonusType type , int val , int subtype , Bonus : : ValueType valType , shared_ptr < ILimiter > limiter , int additionalInfo )
2012-08-26 12:07:48 +03:00
{
giveArtBonus ( aid , createBonus ( type , val , subtype , valType , limiter , additionalInfo ) ) ;
}
2013-06-26 14:18:27 +03:00
void CArtHandler : : giveArtBonus ( ArtifactID aid , Bonus : : BonusType type , int val , int subtype , shared_ptr < IPropagator > propagator /*= nullptr*/ , int additionalInfo )
2012-08-26 12:07:48 +03:00
{
giveArtBonus ( aid , createBonus ( type , val , subtype , propagator , additionalInfo ) ) ;
}
2013-02-11 02:24:57 +03:00
void CArtHandler : : giveArtBonus ( ArtifactID aid , Bonus * bonus )
2012-08-26 12:07:48 +03:00
{
bonus - > sid = aid ;
if ( bonus - > subtype = = Bonus : : MORALE | | bonus - > type = = Bonus : : LUCK )
bonus - > description = artifacts [ aid ] - > Name ( ) + ( bonus - > val > 0 ? " + " : " " ) + boost : : lexical_cast < std : : string > ( bonus - > val ) ;
2011-08-26 23:32:05 +03:00
else
2012-08-26 12:07:48 +03:00
bonus - > description = artifacts [ aid ] - > Name ( ) ;
artifacts [ aid ] - > addNewBonus ( bonus ) ;
2008-11-30 02:15:38 +02:00
}
2012-12-27 14:00:28 +03:00
void CArtHandler : : makeItCreatureArt ( CArtifact * a , bool onlyCreature /*=true*/ )
2012-04-18 16:24:18 +03:00
{
if ( onlyCreature )
{
a - > possibleSlots [ ArtBearer : : HERO ] . clear ( ) ;
2012-05-20 11:39:19 +03:00
a - > possibleSlots [ ArtBearer : : COMMANDER ] . clear ( ) ;
2012-04-18 16:24:18 +03:00
}
a - > possibleSlots [ ArtBearer : : CREATURE ] . push_back ( ArtifactPosition : : CREATURE_SLOT ) ;
2012-09-15 22:16:16 +03:00
}
2008-11-30 02:15:38 +02:00
2013-02-13 01:24:48 +03:00
void CArtHandler : : makeItCreatureArt ( ArtifactID aid , bool onlyCreature /*=true*/ )
2012-05-19 21:27:23 +03:00
{
2012-05-20 11:39:19 +03:00
CArtifact * a = artifacts [ aid ] ;
2012-12-27 14:00:28 +03:00
makeItCreatureArt ( a , onlyCreature ) ;
}
void CArtHandler : : makeItCommanderArt ( CArtifact * a , bool onlyCommander /*= true*/ )
{
2012-05-20 11:39:19 +03:00
if ( onlyCommander )
{
a - > possibleSlots [ ArtBearer : : HERO ] . clear ( ) ;
a - > possibleSlots [ ArtBearer : : CREATURE ] . clear ( ) ;
}
for ( int i = ArtifactPosition : : COMMANDER1 ; i < = ArtifactPosition : : COMMANDER6 ; + + i )
2013-02-12 22:49:40 +03:00
a - > possibleSlots [ ArtBearer : : COMMANDER ] . push_back ( ArtifactPosition ( i ) ) ;
2012-09-15 22:16:16 +03:00
}
2012-05-19 21:27:23 +03:00
2013-02-13 01:24:48 +03:00
void CArtHandler : : makeItCommanderArt ( ArtifactID aid , bool onlyCommander /*= true*/ )
2012-12-27 14:00:28 +03:00
{
CArtifact * a = artifacts [ aid ] ;
makeItCommanderArt ( a , onlyCommander ) ;
}
2013-02-13 01:24:48 +03:00
bool CArtHandler : : legalArtifact ( ArtifactID id )
2013-01-21 18:11:37 +03:00
{
2013-03-02 12:11:52 +03:00
auto art = artifacts [ id ] ;
//assert ( (!art->constituents) || art->constituents->size() ); //artifacts is not combined or has some components
return ( art - > possibleSlots [ ArtBearer : : HERO ] . size ( ) | |
( art - > possibleSlots [ ArtBearer : : COMMANDER ] . size ( ) & & VLC - > modh - > modules . COMMANDERS ) | |
( art - > possibleSlots [ ArtBearer : : CREATURE ] . size ( ) & & VLC - > modh - > modules . STACK_ARTIFACT ) ) & &
! ( art - > constituents ) ; //no combo artifacts spawning
2013-01-21 18:11:37 +03:00
}
2013-02-05 00:58:42 +03:00
void CArtHandler : : initAllowedArtifactsList ( const std : : vector < bool > & allowed )
2010-08-18 12:50:25 +03:00
{
allowedArtifacts . clear ( ) ;
2013-03-29 22:15:52 +03:00
treasures . clear ( ) ;
minors . clear ( ) ;
majors . clear ( ) ;
relics . clear ( ) ;
2013-02-13 01:24:48 +03:00
for ( ArtifactID i = ArtifactID : : SPELLBOOK ; i < ArtifactID : : ART_SELECTION ; i . advance ( 1 ) )
2010-08-18 12:50:25 +03:00
{
2013-01-21 18:11:37 +03:00
if ( allowed [ i ] & & legalArtifact ( i ) )
2010-08-18 12:50:25 +03:00
allowedArtifacts . push_back ( artifacts [ i ] ) ;
}
2012-08-24 12:37:52 +03:00
if ( VLC - > modh - > modules . COMMANDERS ) //allow all commander artifacts for testing
2012-05-20 11:39:19 +03:00
{
for ( int i = 146 ; i < = 155 ; + + i )
{
allowedArtifacts . push_back ( artifacts [ i ] ) ;
}
}
2012-12-14 11:37:46 +03:00
for ( int i = GameConstants : : ARTIFACTS_QUANTITY ; i < artifacts . size ( ) ; + + i ) //allow all new artifacts by default
{
2013-03-02 12:11:52 +03:00
if ( legalArtifact ( ArtifactID ( i ) ) )
2012-12-27 14:00:28 +03:00
allowedArtifacts . push_back ( artifacts [ i ] ) ;
//keep im mind that artifact can be worn by more than one type of bearer
2012-12-14 11:37:46 +03:00
}
2010-08-21 03:39:37 +03:00
}
2010-12-17 20:47:07 +02:00
2013-04-21 15:49:26 +03:00
std : : vector < bool > CArtHandler : : getDefaultAllowed ( ) const
2013-01-06 22:30:12 +03:00
{
2013-02-05 00:58:42 +03:00
std : : vector < bool > allowedArtifacts ;
allowedArtifacts . resize ( 127 , true ) ;
allowedArtifacts . resize ( 141 , false ) ;
allowedArtifacts . resize ( GameConstants : : ARTIFACTS_QUANTITY , true ) ;
2013-01-06 22:30:12 +03:00
return allowedArtifacts ;
}
2013-02-19 01:37:22 +03:00
void CArtHandler : : erasePickedArt ( ArtifactID id )
{
CArtifact * art = artifacts [ id ] ;
if ( auto artifactList = listFromClass ( art - > aClass ) )
{
if ( artifactList - > empty ( ) )
fillList ( * artifactList , art - > aClass ) ;
auto itr = vstd : : find ( * artifactList , art ) ;
if ( itr ! = artifactList - > end ( ) )
{
artifactList - > erase ( itr ) ;
}
else
2013-04-09 17:31:36 +03:00
logGlobal - > warnStream ( ) < < " Problem: cannot erase artifact " < < art - > Name ( ) < < " from list, it was not present " ;
2013-02-19 01:37:22 +03:00
}
else
2013-04-09 17:31:36 +03:00
logGlobal - > warnStream ( ) < < " Problem: cannot find list for artifact " < < art - > Name ( ) < < " , strange class. (special?) " ;
2013-02-19 01:37:22 +03:00
}
boost : : optional < std : : vector < CArtifact * > & > CArtHandler : : listFromClass ( CArtifact : : EartClass artifactClass )
{
switch ( artifactClass )
{
case CArtifact : : ART_TREASURE :
return treasures ;
case CArtifact : : ART_MINOR :
return minors ;
case CArtifact : : ART_MAJOR :
return majors ;
case CArtifact : : ART_RELIC :
return relics ;
default : //special artifacts should not be erased
2013-06-29 16:05:48 +03:00
return nullptr ;
2013-02-19 01:37:22 +03:00
}
}
void CArtHandler : : fillList ( std : : vector < CArtifact * > & listToBeFilled , CArtifact : : EartClass artifactClass )
{
assert ( listToBeFilled . empty ( ) ) ;
2013-06-29 16:05:48 +03:00
for ( auto & elem : allowedArtifacts )
2013-02-19 01:37:22 +03:00
{
2013-06-29 16:05:48 +03:00
if ( elem - > aClass = = artifactClass )
listToBeFilled . push_back ( elem ) ;
2013-02-19 01:37:22 +03:00
}
}
2013-07-21 17:19:29 +03:00
void CArtHandler : : afterLoadFinalization ( )
{
//All artifacts have their id, so we can properly update their bonuses' source ids.
for ( auto & art : artifacts )
{
for ( auto & bonus : art - > getExportedBonusList ( ) )
{
assert ( art = = artifacts [ art - > id ] ) ;
assert ( bonus - > source = = Bonus : : ARTIFACT ) ;
bonus - > sid = art - > id ;
}
}
2014-01-03 02:48:38 +03:00
for ( CArtifact * art : artifacts )
{
2014-06-05 23:51:24 +03:00
VLC - > objtypeh - > loadSubObject ( art - > Name ( ) , JsonNode ( ) , Obj : : ARTIFACT , art - > id . num ) ;
2014-06-04 11:25:13 +03:00
2014-01-03 02:48:38 +03:00
if ( ! art - > advMapDef . empty ( ) )
{
2014-06-04 11:25:13 +03:00
JsonNode templ ;
templ [ " animation " ] . String ( ) = art - > advMapDef ;
2014-01-03 02:48:38 +03:00
2014-05-16 23:50:02 +03:00
// add new template.
2014-01-03 02:48:38 +03:00
// Necessary for objects added via mods that don't have any templates in H3
2014-06-04 11:25:13 +03:00
VLC - > objtypeh - > getHandlerFor ( Obj : : ARTIFACT , art - > id ) - > addTemplate ( templ ) ;
2014-01-03 02:48:38 +03:00
}
2014-06-04 14:15:58 +03:00
// object does not have any templates - this is not usable object (e.g. pseudo-art like lock)
if ( VLC - > objtypeh - > getHandlerFor ( Obj : : ARTIFACT , art - > id ) - > getTemplates ( ) . empty ( ) )
2014-06-05 23:51:24 +03:00
VLC - > objtypeh - > removeSubObject ( Obj : : ARTIFACT , art - > id ) ;
2014-01-03 02:48:38 +03:00
}
2013-07-21 17:19:29 +03:00
}
2010-12-17 20:47:07 +02:00
CArtifactInstance : : CArtifactInstance ( )
{
init ( ) ;
}
CArtifactInstance : : CArtifactInstance ( CArtifact * Art )
{
init ( ) ;
setType ( Art ) ;
}
void CArtifactInstance : : setType ( CArtifact * Art )
{
2010-12-26 16:34:11 +02:00
artType = Art ;
2010-12-17 20:47:07 +02:00
attachTo ( Art ) ;
}
std : : string CArtifactInstance : : nodeName ( ) const
{
2010-12-26 16:34:11 +02:00
return " Artifact instance of " + ( artType ? artType - > Name ( ) : std : : string ( " uninitialized " ) ) + " type " ;
2010-12-17 20:47:07 +02:00
}
CArtifactInstance * CArtifactInstance : : createScroll ( const CSpell * s )
{
2013-06-29 16:05:48 +03:00
auto ret = new CArtifactInstance ( VLC - > arth - > artifacts [ 1 ] ) ;
auto b = new Bonus ( Bonus : : PERMANENT , Bonus : : SPELL , Bonus : : ARTIFACT_INSTANCE , - 1 , 1 , s - > id ) ;
2010-12-17 20:47:07 +02:00
ret - > addNewBonus ( b ) ;
return ret ;
}
void CArtifactInstance : : init ( )
{
2013-02-14 02:55:42 +03:00
id = ArtifactInstanceID ( ) ;
2013-03-30 23:09:50 +03:00
id = static_cast < ArtifactInstanceID > ( ArtifactID : : NONE ) ; //to be randomized
2011-08-26 23:32:05 +03:00
setNodeType ( ARTIFACT_INSTANCE ) ;
2010-12-26 16:34:11 +02:00
}
2014-01-03 02:48:38 +03:00
ArtifactPosition CArtifactInstance : : firstAvailableSlot ( const CArtifactSet * h ) const
{
for ( auto slot : artType - > possibleSlots . at ( h - > bearerType ( ) ) )
{
if ( canBePutAt ( h , slot ) ) //if(artType->fitsAt(h->artifWorn, slot))
{
2010-12-26 16:34:11 +02:00
//we've found a free suitable slot.
return slot ;
}
}
//if haven't find proper slot, use backpack
return firstBackpackSlot ( h ) ;
}
2013-02-12 22:49:40 +03:00
ArtifactPosition CArtifactInstance : : firstBackpackSlot ( const CArtifactSet * h ) const
2010-12-26 16:34:11 +02:00
{
if ( ! artType - > isBig ( ) ) //discard big artifact
2013-02-12 22:49:40 +03:00
return ArtifactPosition (
2013-02-07 02:24:43 +03:00
GameConstants : : BACKPACK_START + h - > artifactsInBackpack . size ( ) ) ;
2010-12-26 16:34:11 +02:00
2013-02-07 02:24:43 +03:00
return ArtifactPosition : : PRE_FIRST ;
2010-12-26 16:34:11 +02:00
}
2013-11-07 15:48:41 +03:00
bool CArtifactInstance : : canBePutAt ( const ArtifactLocation & al , bool assumeDestRemoved /*= false*/ ) const
2010-12-26 16:34:11 +02:00
{
2012-04-14 05:20:22 +03:00
return canBePutAt ( al . getHolderArtSet ( ) , al . slot , assumeDestRemoved ) ;
}
2010-12-29 23:04:22 +02:00
2013-02-12 22:49:40 +03:00
bool CArtifactInstance : : canBePutAt ( const CArtifactSet * artSet , ArtifactPosition slot , bool assumeDestRemoved /*= false*/ ) const
2012-04-14 05:20:22 +03:00
{
if ( slot > = GameConstants : : BACKPACK_START )
{
if ( artType - > isBig ( ) )
2012-01-30 19:07:52 +03:00
return false ;
2010-12-26 16:34:11 +02:00
2012-04-14 05:20:22 +03:00
//TODO backpack limit
return true ;
2012-01-30 19:07:52 +03:00
}
2012-04-14 05:20:22 +03:00
2012-05-22 02:39:35 +03:00
auto possibleSlots = artType - > possibleSlots . find ( artSet - > bearerType ( ) ) ;
if ( possibleSlots = = artType - > possibleSlots . end ( ) )
{
2013-04-09 17:31:36 +03:00
logGlobal - > warnStream ( ) < < " Warning: artifact " < < artType - > Name ( ) < < " doesn't have defined allowed slots for bearer of type "
< < artSet - > bearerType ( ) ;
2012-05-22 02:39:35 +03:00
return false ;
}
if ( ! vstd : : contains ( possibleSlots - > second , slot ) )
2012-01-30 19:07:52 +03:00
return false ;
2012-04-14 05:20:22 +03:00
return artSet - > isPositionFree ( slot , assumeDestRemoved ) ;
2010-12-26 16:34:11 +02:00
}
2012-04-14 19:28:36 +03:00
void CArtifactInstance : : putAt ( ArtifactLocation al )
2010-12-26 16:34:11 +02:00
{
2012-04-14 05:20:22 +03:00
assert ( canBePutAt ( al ) ) ;
2010-12-26 16:34:11 +02:00
2012-04-14 05:20:22 +03:00
al . getHolderArtSet ( ) - > setNewArtSlot ( al . slot , this , false ) ;
if ( al . slot < GameConstants : : BACKPACK_START )
al . getHolderNode ( ) - > attachTo ( this ) ;
2010-12-26 16:34:11 +02:00
}
2012-04-14 19:28:36 +03:00
void CArtifactInstance : : removeFrom ( ArtifactLocation al )
2010-12-26 16:34:11 +02:00
{
2012-04-14 05:20:22 +03:00
assert ( al . getHolderArtSet ( ) - > getArt ( al . slot ) = = this ) ;
al . getHolderArtSet ( ) - > eraseArtSlot ( al . slot ) ;
if ( al . slot < GameConstants : : BACKPACK_START )
al . getHolderNode ( ) - > detachFrom ( this ) ;
2010-12-26 16:34:11 +02:00
//TODO delete me?
2010-12-29 23:04:22 +02:00
}
bool CArtifactInstance : : canBeDisassembled ( ) const
{
2013-06-20 00:26:27 +03:00
return bool ( artType - > constituents ) ;
2010-12-29 23:04:22 +02:00
}
2012-04-14 05:20:22 +03:00
std : : vector < const CArtifact * > CArtifactInstance : : assemblyPossibilities ( const CArtifactSet * h ) const
2010-12-29 23:04:22 +02:00
{
std : : vector < const CArtifact * > ret ;
2013-03-02 19:55:51 +03:00
if ( artType - > constituents ) //combined artifact already: no combining of combined artifacts... for now.
2010-12-29 23:04:22 +02:00
return ret ;
2013-06-29 16:05:48 +03:00
for ( const CArtifact * artifact : artType - > constituentOf )
2010-12-29 23:04:22 +02:00
{
2011-01-18 20:56:14 +02:00
assert ( artifact - > constituents ) ;
bool possible = true ;
2013-06-29 16:05:48 +03:00
for ( const CArtifact * constituent : * artifact - > constituents ) //check if all constituents are available
2010-12-29 23:04:22 +02:00
{
2013-03-02 21:41:25 +03:00
if ( ! h - > hasArt ( constituent - > id , true ) ) //constituent must be equipped
2011-01-18 20:56:14 +02:00
{
possible = false ;
break ;
}
2010-12-29 23:04:22 +02:00
}
2011-01-18 20:56:14 +02:00
if ( possible )
ret . push_back ( artifact ) ;
2010-12-29 23:04:22 +02:00
}
return ret ;
}
2012-04-14 19:28:36 +03:00
void CArtifactInstance : : move ( ArtifactLocation src , ArtifactLocation dst )
2011-01-15 19:58:08 +02:00
{
2012-04-14 05:20:22 +03:00
removeFrom ( src ) ;
putAt ( dst ) ;
2011-01-15 19:58:08 +02:00
}
2011-01-18 20:56:14 +02:00
CArtifactInstance * CArtifactInstance : : createNewArtifactInstance ( CArtifact * Art )
{
if ( ! Art - > constituents )
2012-07-16 19:18:02 +03:00
{
2013-06-29 16:05:48 +03:00
auto ret = new CArtifactInstance ( Art ) ;
2012-07-16 19:18:02 +03:00
if ( dynamic_cast < CGrowingArtifact * > ( Art ) )
{
2013-06-29 16:05:48 +03:00
auto bonus = new Bonus ;
2012-07-16 19:18:02 +03:00
bonus - > type = Bonus : : LEVEL_COUNTER ;
bonus - > val = 0 ;
ret - > addNewBonus ( bonus ) ;
}
return ret ;
}
2011-01-18 20:56:14 +02:00
else
2011-01-22 05:43:20 +02:00
{
2013-06-29 16:05:48 +03:00
auto ret = new CCombinedArtifactInstance ( Art ) ;
2011-01-22 05:43:20 +02:00
ret - > createConstituents ( ) ;
return ret ;
}
2011-01-18 20:56:14 +02:00
}
CArtifactInstance * CArtifactInstance : : createNewArtifactInstance ( int aid )
{
return createNewArtifactInstance ( VLC - > arth - > artifacts [ aid ] ) ;
}
2011-02-04 16:58:14 +02:00
void CArtifactInstance : : deserializationFix ( )
{
setType ( artType ) ;
}
2013-02-13 01:24:48 +03:00
SpellID CArtifactInstance : : getGivenSpellID ( ) const
2011-03-12 23:55:31 +02:00
{
2012-09-20 19:55:21 +03:00
const Bonus * b = getBonusLocalFirst ( Selector : : type ( Bonus : : SPELL ) ) ;
2011-03-12 23:55:31 +02:00
if ( ! b )
{
2013-04-09 17:31:36 +03:00
logGlobal - > warnStream ( ) < < " Warning: " < < nodeName ( ) < < " doesn't bear any spell! " ;
2013-02-13 01:24:48 +03:00
return SpellID : : NONE ;
2011-03-12 23:55:31 +02:00
}
2013-02-13 01:24:48 +03:00
return SpellID ( b - > subtype ) ;
2011-03-12 23:55:31 +02:00
}
2011-07-03 04:03:46 +03:00
bool CArtifactInstance : : isPart ( const CArtifactInstance * supposedPart ) const
{
return supposedPart = = this ;
}
2013-02-12 22:49:40 +03:00
bool CCombinedArtifactInstance : : canBePutAt ( const CArtifactSet * artSet , ArtifactPosition slot , bool assumeDestRemoved /*= false*/ ) const
2010-12-29 23:04:22 +02:00
{
2012-04-14 05:20:22 +03:00
bool canMainArtifactBePlaced = CArtifactInstance : : canBePutAt ( artSet , slot , assumeDestRemoved ) ;
2011-01-28 04:11:58 +02:00
if ( ! canMainArtifactBePlaced )
return false ; //no is no...
2012-04-14 05:20:22 +03:00
if ( slot > = GameConstants : : BACKPACK_START )
2011-01-28 04:11:58 +02:00
return true ; //we can always remove combined art to the backapck
assert ( artType - > constituents ) ;
std : : vector < ConstituentInfo > constituentsToBePlaced = constituentsInfo ; //we'll remove constituents from that list, as we find a suitable slot for them
2011-07-03 04:03:46 +03:00
//it may be that we picked a combined artifact in hero screen (though technically it's still there) to move it
//so we remove from the list all constituents that are already present on dst hero in the form of locks
2013-06-29 16:05:48 +03:00
for ( const ConstituentInfo & constituent : constituentsInfo )
2011-07-03 04:03:46 +03:00
{
2012-04-14 05:20:22 +03:00
if ( constituent . art = = artSet - > getArt ( constituent . slot , false ) ) //no need to worry about locked constituent
2011-07-03 04:03:46 +03:00
constituentsToBePlaced - = constituent ;
}
2012-04-14 05:20:22 +03:00
2011-01-28 04:11:58 +02:00
//we iterate over all active slots and check if constituents fits them
2011-12-14 00:23:17 +03:00
for ( int i = 0 ; i < GameConstants : : BACKPACK_START ; i + + )
2011-01-28 04:11:58 +02:00
{
2013-02-07 02:24:43 +03:00
for ( auto art = constituentsToBePlaced . begin ( ) ; art ! = constituentsToBePlaced . end ( ) ; art + + )
2011-01-28 04:11:58 +02:00
{
2013-02-12 22:49:40 +03:00
if ( art - > art - > canBePutAt ( artSet , ArtifactPosition ( i ) , i = = slot ) ) // i == al.slot because we can remove already worn artifact only from that slot that is our main destination
2011-01-28 04:11:58 +02:00
{
constituentsToBePlaced . erase ( art ) ;
break ;
}
}
}
return constituentsToBePlaced . empty ( ) ;
2010-12-29 23:04:22 +02:00
}
bool CCombinedArtifactInstance : : canBeDisassembled ( ) const
{
return true ;
2011-01-18 20:56:14 +02:00
}
CCombinedArtifactInstance : : CCombinedArtifactInstance ( CArtifact * Art )
2011-06-21 12:31:08 +03:00
: CArtifactInstance ( Art ) //TODO: seems unued, but need to be written
2011-01-18 20:56:14 +02:00
{
}
CCombinedArtifactInstance : : CCombinedArtifactInstance ( )
{
}
void CCombinedArtifactInstance : : createConstituents ( )
{
assert ( artType ) ;
assert ( artType - > constituents ) ;
2013-06-29 16:05:48 +03:00
for ( const CArtifact * art : * artType - > constituents )
2011-01-18 20:56:14 +02:00
{
2013-03-02 21:41:25 +03:00
addAsConstituent ( CArtifactInstance : : createNewArtifactInstance ( art - > id ) , ArtifactPosition : : PRE_FIRST ) ;
2011-01-22 05:43:20 +02:00
}
}
2013-02-12 22:49:40 +03:00
void CCombinedArtifactInstance : : addAsConstituent ( CArtifactInstance * art , ArtifactPosition slot )
2011-01-22 05:43:20 +02:00
{
2013-03-02 21:41:25 +03:00
assert ( vstd : : contains ( * artType - > constituents , art - > artType . get ( ) ) ) ;
2011-07-13 21:39:02 +03:00
assert ( art - > getParentNodes ( ) . size ( ) = = 1 & & art - > getParentNodes ( ) . front ( ) = = art - > artType ) ;
2011-01-22 05:43:20 +02:00
constituentsInfo . push_back ( ConstituentInfo ( art , slot ) ) ;
2011-01-28 04:11:58 +02:00
attachTo ( art ) ;
2011-01-22 05:43:20 +02:00
}
2012-04-14 19:28:36 +03:00
void CCombinedArtifactInstance : : putAt ( ArtifactLocation al )
2011-01-22 05:43:20 +02:00
{
2012-04-14 05:20:22 +03:00
if ( al . slot > = GameConstants : : BACKPACK_START )
2011-01-22 05:43:20 +02:00
{
2012-04-14 05:20:22 +03:00
CArtifactInstance : : putAt ( al ) ;
2013-06-29 16:05:48 +03:00
for ( ConstituentInfo & ci : constituentsInfo )
2013-02-07 02:24:43 +03:00
ci . slot = ArtifactPosition : : PRE_FIRST ;
2011-01-22 05:43:20 +02:00
}
else
{
2012-04-14 05:20:22 +03:00
CArtifactInstance * mainConstituent = figureMainConstituent ( al ) ; //it'll be replaced with combined artifact, not a lock
CArtifactInstance : : putAt ( al ) ; //puts combined art (this)
2011-01-22 05:43:20 +02:00
2013-06-29 16:05:48 +03:00
for ( ConstituentInfo & ci : constituentsInfo )
2011-01-22 05:43:20 +02:00
{
if ( ci . art ! = mainConstituent )
{
2012-04-14 05:20:22 +03:00
const ArtifactLocation suggestedPos ( al . artHolder , ci . slot ) ;
const bool inActiveSlot = vstd : : isbetween ( ci . slot , 0 , GameConstants : : BACKPACK_START ) ;
const bool suggestedPosValid = ci . art - > canBePutAt ( suggestedPos ) ;
2013-02-12 22:49:40 +03:00
ArtifactPosition pos = ArtifactPosition : : PRE_FIRST ;
2012-09-15 22:16:16 +03:00
if ( inActiveSlot & & suggestedPosValid ) //there is a valid suggestion where to place lock
2011-01-22 05:43:20 +02:00
pos = ci . slot ;
else
2012-04-14 05:20:22 +03:00
ci . slot = pos = ci . art - > firstAvailableSlot ( al . getHolderArtSet ( ) ) ;
2011-01-22 05:43:20 +02:00
2011-12-14 00:23:17 +03:00
assert ( pos < GameConstants : : BACKPACK_START ) ;
2012-04-14 05:20:22 +03:00
al . getHolderArtSet ( ) - > setNewArtSlot ( pos , ci . art , true ) ; //sets as lock
2011-01-22 05:43:20 +02:00
}
else
{
2013-02-07 02:24:43 +03:00
ci . slot = ArtifactPosition : : PRE_FIRST ;
2011-01-22 05:43:20 +02:00
}
}
}
}
2012-04-14 19:28:36 +03:00
void CCombinedArtifactInstance : : removeFrom ( ArtifactLocation al )
2011-01-22 05:43:20 +02:00
{
2012-04-14 05:20:22 +03:00
if ( al . slot > = GameConstants : : BACKPACK_START )
2011-01-22 05:43:20 +02:00
{
2012-04-14 05:20:22 +03:00
CArtifactInstance : : removeFrom ( al ) ;
2011-01-22 05:43:20 +02:00
}
else
{
2013-06-29 16:05:48 +03:00
for ( ConstituentInfo & ci : constituentsInfo )
2011-01-22 05:43:20 +02:00
{
if ( ci . slot > = 0 )
{
2012-04-14 05:20:22 +03:00
al . getHolderArtSet ( ) - > eraseArtSlot ( ci . slot ) ;
2013-02-07 02:24:43 +03:00
ci . slot = ArtifactPosition : : PRE_FIRST ;
2011-01-22 05:43:20 +02:00
}
else
{
//main constituent
2012-04-14 05:20:22 +03:00
CArtifactInstance : : removeFrom ( al ) ;
2011-01-22 05:43:20 +02:00
}
}
2011-01-18 20:56:14 +02:00
}
}
2012-04-14 19:28:36 +03:00
CArtifactInstance * CCombinedArtifactInstance : : figureMainConstituent ( const ArtifactLocation al )
2011-01-22 05:43:20 +02:00
{
2013-06-26 14:18:27 +03:00
CArtifactInstance * mainConstituent = nullptr ; //it'll be replaced with combined artifact, not a lock
2013-06-29 16:05:48 +03:00
for ( ConstituentInfo & ci : constituentsInfo )
2012-04-14 05:20:22 +03:00
if ( ci . slot = = al . slot )
2011-01-22 05:43:20 +02:00
mainConstituent = ci . art ;
if ( ! mainConstituent )
{
2013-06-29 16:05:48 +03:00
for ( ConstituentInfo & ci : constituentsInfo )
2011-01-22 05:43:20 +02:00
{
2012-04-14 05:20:22 +03:00
if ( vstd : : contains ( ci . art - > artType - > possibleSlots [ al . getHolderArtSet ( ) - > bearerType ( ) ] , al . slot ) )
2011-01-22 05:43:20 +02:00
{
mainConstituent = ci . art ;
}
}
}
return mainConstituent ;
}
2011-01-18 20:56:14 +02:00
2011-02-04 16:58:14 +02:00
void CCombinedArtifactInstance : : deserializationFix ( )
{
2013-06-29 16:05:48 +03:00
for ( ConstituentInfo & ci : constituentsInfo )
2011-02-04 16:58:14 +02:00
attachTo ( ci . art ) ;
}
2011-07-03 04:03:46 +03:00
bool CCombinedArtifactInstance : : isPart ( const CArtifactInstance * supposedPart ) const
{
bool me = CArtifactInstance : : isPart ( supposedPart ) ;
if ( me )
return true ;
//check for constituents
2013-06-29 16:05:48 +03:00
for ( const ConstituentInfo & constituent : constituentsInfo )
2011-07-03 04:03:46 +03:00
if ( constituent . art = = supposedPart )
return true ;
return false ;
}
2013-06-26 14:18:27 +03:00
CCombinedArtifactInstance : : ConstituentInfo : : ConstituentInfo ( CArtifactInstance * Art /*= nullptr*/ , ArtifactPosition Slot /*= -1*/ )
2011-01-18 20:56:14 +02:00
{
art = Art ;
slot = Slot ;
2011-06-24 20:43:02 +03:00
}
2011-07-03 04:03:46 +03:00
bool CCombinedArtifactInstance : : ConstituentInfo : : operator = = ( const ConstituentInfo & rhs ) const
{
return art = = rhs . art & & slot = = rhs . slot ;
}
2012-01-30 19:07:52 +03:00
2013-02-12 22:49:40 +03:00
const CArtifactInstance * CArtifactSet : : getArt ( ArtifactPosition pos , bool excludeLocked /*= true*/ ) const
2011-06-24 20:43:02 +03:00
{
if ( const ArtSlotInfo * si = getSlot ( pos ) )
{
if ( si - > artifact & & ( ! excludeLocked | | ! si - > locked ) )
return si - > artifact ;
}
2013-06-26 14:18:27 +03:00
return nullptr ;
2011-06-24 20:43:02 +03:00
}
2013-02-12 22:49:40 +03:00
CArtifactInstance * CArtifactSet : : getArt ( ArtifactPosition pos , bool excludeLocked /*= true*/ )
2011-06-24 20:43:02 +03:00
{
2012-04-14 05:20:22 +03:00
return const_cast < CArtifactInstance * > ( ( const_cast < const CArtifactSet * > ( this ) ) - > getArt ( pos , excludeLocked ) ) ;
2011-06-24 20:43:02 +03:00
}
2013-02-12 22:49:40 +03:00
ArtifactPosition CArtifactSet : : getArtPos ( int aid , bool onlyWorn /*= true*/ ) const
2011-06-24 20:43:02 +03:00
{
2013-02-07 02:24:43 +03:00
for ( auto i = artifactsWorn . cbegin ( ) ; i ! = artifactsWorn . cend ( ) ; i + + )
2011-06-24 20:43:02 +03:00
if ( i - > second . artifact - > artType - > id = = aid )
return i - > first ;
if ( onlyWorn )
2013-02-07 02:24:43 +03:00
return ArtifactPosition : : PRE_FIRST ;
2011-06-24 20:43:02 +03:00
for ( int i = 0 ; i < artifactsInBackpack . size ( ) ; i + + )
if ( artifactsInBackpack [ i ] . artifact - > artType - > id = = aid )
2013-02-12 22:49:40 +03:00
return ArtifactPosition ( GameConstants : : BACKPACK_START + i ) ;
2011-06-24 20:43:02 +03:00
2013-02-07 02:24:43 +03:00
return ArtifactPosition : : PRE_FIRST ;
2011-06-24 20:43:02 +03:00
}
2013-02-12 22:49:40 +03:00
ArtifactPosition CArtifactSet : : getArtPos ( const CArtifactInstance * art ) const
2011-06-24 20:43:02 +03:00
{
2013-06-29 16:05:48 +03:00
for ( auto i : artifactsWorn )
2013-02-07 02:24:43 +03:00
if ( i . second . artifact = = art )
return i . first ;
2011-06-24 20:43:02 +03:00
for ( int i = 0 ; i < artifactsInBackpack . size ( ) ; i + + )
if ( artifactsInBackpack [ i ] . artifact = = art )
2013-02-12 22:49:40 +03:00
return ArtifactPosition ( GameConstants : : BACKPACK_START + i ) ;
2011-06-24 20:43:02 +03:00
2013-02-07 02:24:43 +03:00
return ArtifactPosition : : PRE_FIRST ;
2011-06-24 20:43:02 +03:00
}
2013-02-14 02:55:42 +03:00
const CArtifactInstance * CArtifactSet : : getArtByInstanceId ( ArtifactInstanceID artInstId ) const
2011-06-24 20:43:02 +03:00
{
2013-06-29 16:05:48 +03:00
for ( auto i : artifactsWorn )
2013-02-07 02:24:43 +03:00
if ( i . second . artifact - > id = = artInstId )
return i . second . artifact ;
2011-06-24 20:43:02 +03:00
2013-06-29 16:05:48 +03:00
for ( auto i : artifactsInBackpack )
2013-02-07 02:24:43 +03:00
if ( i . artifact - > id = = artInstId )
return i . artifact ;
2011-06-24 20:43:02 +03:00
2013-06-26 14:18:27 +03:00
return nullptr ;
2011-06-24 20:43:02 +03:00
}
2012-04-14 05:20:22 +03:00
bool CArtifactSet : : hasArt ( ui32 aid , bool onlyWorn /*= false*/ ) const
{
2013-02-07 02:24:43 +03:00
return getArtPos ( aid , onlyWorn ) ! = ArtifactPosition : : PRE_FIRST ;
2012-04-14 05:20:22 +03:00
}
2014-01-03 02:48:38 +03:00
const ArtSlotInfo * CArtifactSet : : getSlot ( ArtifactPosition pos ) const
{
if ( vstd : : contains ( artifactsWorn , pos ) )
return & artifactsWorn . at ( pos ) ;
if ( pos > = ArtifactPosition : : AFTER_LAST )
{
int backpackPos = ( int ) pos - GameConstants : : BACKPACK_START ;
2011-06-24 20:43:02 +03:00
if ( backpackPos < 0 | | backpackPos > = artifactsInBackpack . size ( ) )
2013-06-26 14:18:27 +03:00
return nullptr ;
2011-06-24 20:43:02 +03:00
else
return & artifactsInBackpack [ backpackPos ] ;
}
2013-06-26 14:18:27 +03:00
return nullptr ;
2011-06-24 20:43:02 +03:00
}
2013-02-12 22:49:40 +03:00
bool CArtifactSet : : isPositionFree ( ArtifactPosition pos , bool onlyLockCheck /*= false*/ ) const
2012-04-14 05:20:22 +03:00
{
if ( const ArtSlotInfo * s = getSlot ( pos ) )
return ( onlyLockCheck | | ! s - > artifact ) & & ! s - > locked ;
return true ; //no slot means not used
}
2013-02-12 22:49:40 +03:00
si32 CArtifactSet : : getArtTypeId ( ArtifactPosition pos ) const
2011-06-24 20:43:02 +03:00
{
const CArtifactInstance * const a = getArt ( pos ) ;
if ( ! a )
{
2013-04-09 17:31:36 +03:00
logGlobal - > warnStream ( ) < < ( dynamic_cast < const CGHeroInstance * > ( this ) ) - > name < < " has no artifact at " < < pos < < " (getArtTypeId) " ;
2011-06-24 20:43:02 +03:00
return - 1 ;
}
return a - > artType - > id ;
}
CArtifactSet : : ~ CArtifactSet ( )
{
}
2013-02-12 22:49:40 +03:00
ArtSlotInfo & CArtifactSet : : retreiveNewArtSlot ( ArtifactPosition slot )
2011-06-24 20:43:02 +03:00
{
assert ( ! vstd : : contains ( artifactsWorn , slot ) ) ;
2012-09-15 22:16:16 +03:00
ArtSlotInfo & ret = slot < GameConstants : : BACKPACK_START
2011-06-24 20:43:02 +03:00
? artifactsWorn [ slot ]
2011-12-14 00:23:17 +03:00
: * artifactsInBackpack . insert ( artifactsInBackpack . begin ( ) + ( slot - GameConstants : : BACKPACK_START ) , ArtSlotInfo ( ) ) ;
2011-06-24 20:43:02 +03:00
return ret ;
}
2013-02-12 22:49:40 +03:00
void CArtifactSet : : setNewArtSlot ( ArtifactPosition slot , CArtifactInstance * art , bool locked )
2012-04-14 05:20:22 +03:00
{
ArtSlotInfo & asi = retreiveNewArtSlot ( slot ) ;
asi . artifact = art ;
asi . locked = locked ;
}
2013-02-12 22:49:40 +03:00
void CArtifactSet : : eraseArtSlot ( ArtifactPosition slot )
2011-06-24 20:43:02 +03:00
{
2011-12-14 00:23:17 +03:00
if ( slot < GameConstants : : BACKPACK_START )
2011-06-24 20:43:02 +03:00
{
artifactsWorn . erase ( slot ) ;
}
else
{
2013-02-12 22:49:40 +03:00
slot = ArtifactPosition ( slot - GameConstants : : BACKPACK_START ) ;
2011-06-24 20:43:02 +03:00
artifactsInBackpack . erase ( artifactsInBackpack . begin ( ) + slot ) ;
}
2011-08-13 13:54:23 +03:00
}
2012-04-14 05:20:22 +03:00
void CArtifactSet : : artDeserializationFix ( CBonusSystemNode * node )
2011-08-13 13:54:23 +03:00
{
2013-06-29 16:05:48 +03:00
for ( auto & elem : artifactsWorn )
if ( elem . second . artifact & & ! elem . second . locked )
node - > attachTo ( elem . second . artifact ) ;
2012-04-14 19:28:36 +03:00
}