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"
2023-03-15 21:34:29 +02:00
# include "GameSettings.h"
2017-05-26 18:51:45 +02:00
# include "CCreatureHandler.h"
2015-02-02 10:25:26 +02:00
# include "spells/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"
2016-01-24 01:27:14 +02:00
# include "StringConstants.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"
2016-02-13 18:43:05 +02:00
# include "mapping/CMap.h"
2016-11-13 12:38:42 +02:00
# include "serializer/JsonSerializeFormat.h"
2014-06-05 19:52:14 +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 ) \
2014-10-02 18:43:46 +03:00
ART_POS ( HEAD )
2012-12-10 16:55:54 +03:00
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_BEGIN
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
int32_t CArtifact : : getIndex ( ) const
{
return id . toEnum ( ) ;
}
int32_t CArtifact : : getIconIndex ( ) const
{
return iconIndex ;
}
2023-01-18 23:56:01 +02:00
std : : string CArtifact : : getJsonKey ( ) const
2009-04-04 01:34:31 +03:00
{
2023-01-18 23:56:01 +02:00
return modScope + ' : ' + identifier ;
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
}
void CArtifact : : registerIcons ( const IconRegistar & cb ) const
{
2022-11-29 14:47:51 +02:00
cb ( getIconIndex ( ) , 0 , " ARTIFACT " , image ) ;
cb ( getIconIndex ( ) , 0 , " ARTIFACTLARGE " , large ) ;
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
}
ArtifactID CArtifact : : getId ( ) const
{
return id ;
}
2023-04-05 02:26:29 +02:00
const IBonusBearer * CArtifact : : getBonusBearer ( ) const
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 this ;
}
2023-01-02 15:58:56 +02:00
std : : string CArtifact : : getDescriptionTranslated ( ) const
{
return VLC - > generaltexth - > translate ( getDescriptionTextID ( ) ) ;
}
std : : string CArtifact : : getEventTranslated ( ) const
{
return VLC - > generaltexth - > translate ( getEventTextID ( ) ) ;
}
std : : string CArtifact : : getNameTranslated ( ) const
{
return VLC - > generaltexth - > translate ( getNameTextID ( ) ) ;
}
std : : string CArtifact : : getDescriptionTextID ( ) const
{
2023-01-18 23:56:01 +02:00
return TextIdentifier ( " artifact " , modScope , identifier , " description " ) . get ( ) ;
2023-01-02 15:58:56 +02:00
}
std : : string CArtifact : : getEventTextID ( ) const
2009-04-04 01:34:31 +03:00
{
2023-01-18 23:56:01 +02:00
return TextIdentifier ( " artifact " , modScope , identifier , " event " ) . get ( ) ;
2012-12-06 22:03:47 +03:00
}
2023-01-02 15:58:56 +02:00
std : : string CArtifact : : getNameTextID ( ) const
2012-12-06 22:03:47 +03:00
{
2023-01-18 23:56:01 +02:00
return TextIdentifier ( " artifact " , modScope , identifier , " name " ) . get ( ) ;
2009-04-04 01:34:31 +03:00
}
2009-12-30 17:33:28 +02:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
uint32_t CArtifact : : getPrice ( ) const
{
return price ;
}
CreatureID CArtifact : : getWarMachine ( ) const
{
return warMachine ;
}
2017-05-26 18:51:45 +02:00
bool CArtifact : : isBig ( ) const
2009-12-30 17:33:28 +02:00
{
2017-05-26 18:51:45 +02:00
return warMachine ! = CreatureID : : NONE ;
2009-12-30 17:33:28 +02:00
}
2017-05-26 18:51:45 +02:00
bool CArtifact : : isTradable ( ) const
2014-12-24 19:43:35 +02:00
{
2017-05-26 18:51:45 +02:00
switch ( id )
{
case ArtifactID : : SPELLBOOK :
case ArtifactID : : GRAIL :
return false ;
default :
return ! isBig ( ) ;
}
2014-12-24 19:43:35 +02:00
}
2023-03-13 12:28:33 +02:00
bool CArtifact : : canBeDisassembled ( ) const
{
return ! ( constituents = = nullptr ) ;
}
bool CArtifact : : canBePutAt ( const CArtifactSet * artSet , ArtifactPosition slot , bool assumeDestRemoved ) const
{
auto simpleArtCanBePutAt = [ this ] ( const CArtifactSet * artSet , ArtifactPosition slot , bool assumeDestRemoved ) - > bool
{
if ( ArtifactUtils : : isSlotBackpack ( slot ) )
{
2023-03-18 12:44:01 +02:00
if ( isBig ( ) | | ! ArtifactUtils : : isBackpackFreeSlots ( artSet ) )
2023-03-13 12:28:33 +02:00
return false ;
return true ;
}
2023-03-21 12:13:53 +02:00
if ( ! vstd : : contains ( possibleSlots . at ( artSet - > bearerType ( ) ) , slot ) )
2023-03-13 12:28:33 +02:00
return false ;
return artSet - > isPositionFree ( slot , assumeDestRemoved ) ;
} ;
2023-03-21 12:13:53 +02:00
auto artCanBePutAt = [ this , simpleArtCanBePutAt ] ( const CArtifactSet * artSet , ArtifactPosition slot , bool assumeDestRemoved ) - > bool
2023-03-13 12:28:33 +02:00
{
2023-03-21 12:13:53 +02:00
if ( canBeDisassembled ( ) )
2023-03-13 12:28:33 +02:00
{
2023-03-21 12:13:53 +02:00
if ( ! simpleArtCanBePutAt ( artSet , slot , assumeDestRemoved ) )
2023-03-13 12:28:33 +02:00
return false ;
2023-03-21 12:13:53 +02:00
if ( ArtifactUtils : : isSlotBackpack ( slot ) )
return true ;
CArtifactFittingSet fittingSet ( artSet - > bearerType ( ) ) ;
fittingSet . artifactsWorn = artSet - > artifactsWorn ;
if ( assumeDestRemoved )
fittingSet . removeArtifact ( slot ) ;
assert ( constituents ) ;
for ( const auto art : * constituents )
{
auto possibleSlot = ArtifactUtils : : getArtAnyPosition ( & fittingSet , art - > getId ( ) ) ;
if ( ArtifactUtils : : isSlotEquipment ( possibleSlot ) )
{
fittingSet . setNewArtSlot ( possibleSlot , nullptr , true ) ;
}
else
{
return false ;
}
2023-03-13 12:28:33 +02:00
}
2023-03-21 12:13:53 +02:00
return true ;
}
else
{
return simpleArtCanBePutAt ( artSet , slot , assumeDestRemoved ) ;
2023-03-13 12:28:33 +02:00
}
2023-03-21 12:13:53 +02:00
} ;
if ( slot = = ArtifactPosition : : TRANSITION_POS )
2023-03-13 12:28:33 +02:00
return true ;
2023-03-21 12:13:53 +02:00
if ( slot = = ArtifactPosition : : FIRST_AVAILABLE )
{
for ( const auto & slot : possibleSlots . at ( artSet - > bearerType ( ) ) )
{
if ( artCanBePutAt ( artSet , slot , assumeDestRemoved ) )
return true ;
}
return artCanBePutAt ( artSet , GameConstants : : BACKPACK_START , assumeDestRemoved ) ;
}
else if ( ArtifactUtils : : isSlotBackpack ( slot ) )
{
return artCanBePutAt ( artSet , GameConstants : : BACKPACK_START , assumeDestRemoved ) ;
2023-03-13 12:28:33 +02:00
}
else
{
2023-03-21 12:13:53 +02:00
return artCanBePutAt ( artSet , slot , assumeDestRemoved ) ;
2023-03-13 12:28:33 +02:00
}
}
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
}
2023-03-13 23:26:44 +02:00
//This destructor should be placed here to avoid side effects
CArtifact : : ~ CArtifact ( ) = default ;
2010-05-09 22:10:59 +03:00
2010-07-23 15:02:15 +03:00
int CArtifact : : getArtClassSerial ( ) const
{
2014-12-24 17:49:12 +02:00
if ( id = = ArtifactID : : SPELL_SCROLL )
2010-07-23 15:02:15 +03:00
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
{
2023-01-18 23:56:01 +02:00
return " Artifact: " + getNameTranslated ( ) ;
2010-12-17 20:47:07 +02:00
}
2010-11-10 02:06:25 +02:00
2016-09-19 23:36:35 +02:00
void CArtifact : : addNewBonus ( const std : : shared_ptr < Bonus > & b )
2012-12-13 17:27:33 +03:00
{
b - > source = Bonus : : ARTIFACT ;
b - > duration = Bonus : : PERMANENT ;
2023-01-02 15:58:56 +02:00
b - > description = getNameTranslated ( ) ;
2012-12-13 17:27:33 +03:00
CBonusSystemNode : : addNewBonus ( b ) ;
}
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
void CArtifact : : updateFrom ( const JsonNode & data )
{
//TODO:CArtifact::updateFrom
}
void CArtifact : : serializeJson ( JsonSerializeFormat & handler )
{
}
2012-07-16 19:18:02 +03:00
void CGrowingArtifact : : levelUpArtifact ( CArtifactInstance * art )
{
2016-09-19 23:36:35 +02:00
auto b = std : : make_shared < Bonus > ( ) ;
b - > type = Bonus : : LEVEL_COUNTER ;
b - > val = 1 ;
b - > duration = Bonus : : COMMANDER_KILLED ;
art - > accumulateBonus ( b ) ;
2012-07-16 19:18:02 +03:00
2023-03-13 23:26:44 +02:00
for ( const auto & bonus : bonusesPerLevel )
2012-07-16 19:18:02 +03:00
{
if ( art - > valOfBonuses ( Bonus : : LEVEL_COUNTER ) % bonus . first = = 0 ) //every n levels
{
2016-09-19 23:36:35 +02:00
art - > accumulateBonus ( std : : make_shared < Bonus > ( bonus . second ) ) ;
2012-07-16 19:18:02 +03:00
}
}
2023-03-13 23:26:44 +02:00
for ( const auto & bonus : thresholdBonuses )
2012-07-16 19:18:02 +03:00
{
if ( art - > valOfBonuses ( Bonus : : LEVEL_COUNTER ) = = bonus . first ) //every n levels
{
2016-09-19 23:36:35 +02:00
art - > addNewBonus ( std : : make_shared < Bonus > ( bonus . second ) ) ;
2012-07-16 19:18:02 +03:00
}
}
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
CArtHandler : : ~ CArtHandler ( ) = default ;
2010-02-16 16:39:56 +02:00
2023-03-15 21:34:29 +02:00
std : : vector < JsonNode > CArtHandler : : loadLegacyData ( )
2007-06-07 23:16:19 +03:00
{
2023-03-15 21:34:29 +02:00
size_t dataSize = VLC - > settings ( ) - > getInteger ( EGameSettings : : TEXTS_ARTIFACT ) ;
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
objects . resize ( dataSize ) ;
2013-04-21 15:49:26 +03:00
std : : vector < JsonNode > h3Data ;
h3Data . reserve ( dataSize ) ;
2013-03-02 19:55:51 +03:00
2014-10-02 18:43:46 +03:00
# define ART_POS(x) #x ,
const std : : vector < std : : string > artSlots = { ART_POS_LIST } ;
2013-03-12 17:56:23 +03:00
# 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 =
2014-10-02 18:43:46 +03:00
{ { ' 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
2023-03-13 23:26:44 +02:00
for ( const 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 )
{
2023-03-13 23:26:44 +02:00
auto * object = loadFromJson ( scope , data , name , objects . size ( ) ) ;
2013-03-12 17:56:23 +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
object - > iconIndex = object - > getIndex ( ) + 5 ;
2015-11-14 15:50:29 +02:00
2023-03-13 23:26:44 +02:00
objects . emplace_back ( object ) ;
2015-11-14 15:50:29 +02:00
2016-02-21 19:58:09 +02:00
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
{
2023-03-13 23:26:44 +02:00
auto * object = loadFromJson ( scope , data , name , index ) ;
2015-11-14 15:50:29 +02:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
object - > iconIndex = object - > getIndex ( ) ;
2015-11-14 15:50:29 +02:00
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
assert ( objects [ index ] = = nullptr ) ; // ensure that this id was not loaded before
objects [ index ] = object ;
2015-11-14 15:50:29 +02:00
2016-02-21 19:58:09 +02:00
registerObject ( scope , " artifact " , name , object - > id ) ;
2012-12-10 16:55:54 +03:00
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const std : : vector < std : : string > & CArtHandler : : getTypeNames ( ) const
{
static const std : : vector < std : : string > typeNames = { " artifact " } ;
return typeNames ;
}
CArtifact * CArtHandler : : loadFromJson ( const std : : string & scope , const JsonNode & node , const std : : string & identifier , size_t index )
2012-12-10 16:55:54 +03:00
{
2023-01-18 23:56:01 +02:00
assert ( identifier . find ( ' : ' ) = = std : : string : : npos ) ;
assert ( ! scope . empty ( ) ) ;
2023-03-13 23:26:44 +02:00
CArtifact * art = nullptr ;
2013-03-12 17:56:23 +03:00
2023-03-15 21:34:29 +02:00
if ( ! VLC - > settings ( ) - > getBoolean ( EGameSettings : : MODULE_COMMANDERS ) | | node [ " growing " ] . isNull ( ) )
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
{
2013-03-12 17:56:23 +03:00
art = new CArtifact ( ) ;
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
}
2013-03-12 17:56:23 +03:00
else
{
2023-03-13 23:26:44 +02:00
auto * growing = new CGrowingArtifact ( ) ;
2013-03-12 17:56:23 +03:00
loadGrowingArt ( growing , node ) ;
art = growing ;
}
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
art - > id = ArtifactID ( index ) ;
2015-08-24 10:55:45 +02:00
art - > identifier = identifier ;
2023-01-02 15:58:56 +02:00
art - > modScope = scope ;
2012-12-10 16:55:54 +03:00
const JsonNode & text = node [ " text " ] ;
2023-01-02 15:58:56 +02:00
2023-02-09 15:03:49 +02:00
VLC - > generaltexth - > registerString ( scope , art - > getNameTextID ( ) , text [ " name " ] . String ( ) ) ;
VLC - > generaltexth - > registerString ( scope , art - > getDescriptionTextID ( ) , text [ " description " ] . String ( ) ) ;
VLC - > generaltexth - > registerString ( scope , art - > getEventTextID ( ) , 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
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
if ( ! graphics [ " large " ] . isNull ( ) )
2013-04-02 20:06:43 +03:00
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
2020-10-01 10:38:06 +02:00
art - > price = static_cast < ui32 > ( node [ " value " ] . Float ( ) ) ;
2013-03-12 17:56:23 +03:00
loadSlots ( art , node ) ;
loadClass ( art , node ) ;
loadType ( art , node ) ;
loadComponents ( art , node ) ;
2023-03-13 23:26:44 +02:00
for ( const auto & b : node [ " bonuses " ] . Vector ( ) )
2013-03-12 17:56:23 +03:00
{
2016-09-19 23:36:35 +02: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
}
2017-05-26 18:51:45 +02:00
const JsonNode & warMachine = node [ " warMachine " ] ;
2022-11-15 02:20:55 +02:00
if ( warMachine . getType ( ) = = JsonNode : : JsonType : : DATA_STRING & & ! warMachine . String ( ) . empty ( ) )
2017-05-26 18:51:45 +02:00
{
VLC - > modh - > identifiers . requestIdentifier ( " creature " , warMachine , [ = ] ( si32 id )
{
art - > warMachine = CreatureID ( id ) ;
//this assumes that creature object is stored before registration
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
VLC - > creh - > objects . at ( id ) - > warMachine = art - > id ;
2017-05-26 18:51:45 +02:00
} ) ;
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
VLC - > modh - > identifiers . requestIdentifier ( scope , " object " , " artifact " , [ = ] ( si32 index )
{
JsonNode conf ;
conf . setMeta ( scope ) ;
2023-01-19 01:43:12 +02:00
VLC - > objtypeh - > loadSubObject ( art - > identifier , conf , Obj : : ARTIFACT , art - > getIndex ( ) ) ;
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
if ( ! art - > advMapDef . empty ( ) )
{
JsonNode templ ;
templ [ " animation " ] . String ( ) = art - > advMapDef ;
2022-11-29 22:34:32 +02:00
templ . setMeta ( scope ) ;
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
// add new template.
// Necessary for objects added via mods that don't have any templates in H3
VLC - > objtypeh - > getHandlerFor ( Obj : : ARTIFACT , art - > getIndex ( ) ) - > addTemplate ( templ ) ;
}
// object does not have any templates - this is not usable object (e.g. pseudo-art like lock)
if ( VLC - > objtypeh - > getHandlerFor ( Obj : : ARTIFACT , art - > getIndex ( ) ) - > getTemplates ( ) . empty ( ) )
VLC - > objtypeh - > removeSubObject ( Obj : : ARTIFACT , art - > getIndex ( ) ) ;
} ) ;
2013-03-12 17:56:23 +03:00
return art ;
}
2023-02-12 22:39:17 +02:00
ArtifactPosition : : ArtifactPosition ( std : : string slotName ) :
num ( ArtifactPosition : : PRE_FIRST )
2013-03-12 17:56:23 +03:00
{
2014-10-02 18:43:46 +03:00
# define ART_POS(x) { #x, ArtifactPosition::x },
static const std : : map < std : : string , ArtifactPosition > artifactPositionMap = { ART_POS_LIST } ;
2013-03-12 17:56:23 +03:00
# undef ART_POS
2014-06-22 13:39:40 +03:00
auto it = artifactPositionMap . find ( slotName ) ;
if ( it ! = artifactPositionMap . end ( ) )
2023-02-12 22:39:17 +02:00
num = it - > second ;
2023-02-15 12:10:39 +02:00
else
logMod - > warn ( " Warning! Artifact slot %s not recognized! " , slotName ) ;
2014-06-22 13:39:40 +03:00
}
2013-03-12 17:56:23 +03:00
2023-03-13 23:26:44 +02:00
void CArtHandler : : addSlot ( CArtifact * art , const std : : string & slotID ) const
2014-06-22 13:39:40 +03:00
{
2015-11-14 15:50:29 +02:00
static const std : : vector < ArtifactPosition > miscSlots =
2014-10-03 23:34:13 +03:00
{
ArtifactPosition : : MISC1 , ArtifactPosition : : MISC2 , ArtifactPosition : : MISC3 , ArtifactPosition : : MISC4 , ArtifactPosition : : MISC5
} ;
2015-11-14 15:50:29 +02:00
2014-10-03 23:34:13 +03:00
static const std : : vector < ArtifactPosition > ringSlots =
{
2023-03-07 13:13:30 +02:00
ArtifactPosition : : RIGHT_RING , ArtifactPosition : : LEFT_RING
2014-10-03 23:34:13 +03:00
} ;
2015-11-14 15:50:29 +02:00
2013-03-12 17:56:23 +03:00
if ( slotID = = " MISC " )
2012-12-14 11:37:46 +03:00
{
2014-10-03 23:34:13 +03:00
vstd : : concatenate ( art - > possibleSlots [ ArtBearer : : HERO ] , miscSlots ) ;
2013-03-12 17:56:23 +03:00
}
else if ( slotID = = " RING " )
{
2014-10-03 23:34:13 +03:00
vstd : : concatenate ( art - > possibleSlots [ ArtBearer : : HERO ] , ringSlots ) ;
2013-03-12 17:56:23 +03:00
}
else
{
2023-02-12 22:39:17 +02:00
auto slot = ArtifactPosition ( slotID ) ;
2014-06-22 13:39:40 +03:00
if ( slot ! = ArtifactPosition : : PRE_FIRST )
2023-03-07 13:13:30 +02: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
2023-03-13 23:26:44 +02:00
void CArtHandler : : loadSlots ( CArtifact * art , const JsonNode & node ) const
2013-03-12 17:56:23 +03:00
{
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
{
2017-11-26 23:18:18 +02:00
if ( node [ " slot " ] . getType ( ) = = JsonNode : : JsonType : : DATA_STRING )
2013-03-12 17:56:23 +03:00
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
}
2023-03-07 13:13:30 +02:00
std : : sort ( art - > possibleSlots . at ( ArtBearer : : HERO ) . begin ( ) , art - > possibleSlots . at ( ArtBearer : : HERO ) . end ( ) ) ;
2012-12-10 16:55:54 +03:00
}
2013-03-02 19:55:51 +03:00
}
2023-03-13 23:26:44 +02:00
CArtifact : : EartClass CArtHandler : : stringToClass ( const std : : string & className )
2013-03-02 19:55:51 +03:00
{
2014-10-02 18:43:46 +03:00
static const std : : map < std : : string , CArtifact : : EartClass > artifactClassMap =
2015-11-14 15:50:29 +02:00
{
2014-10-02 18:43:46 +03:00
{ " TREASURE " , CArtifact : : ART_TREASURE } ,
{ " MINOR " , CArtifact : : ART_MINOR } ,
{ " MAJOR " , CArtifact : : ART_MAJOR } ,
{ " RELIC " , CArtifact : : ART_RELIC } ,
{ " SPECIAL " , CArtifact : : ART_SPECIAL }
} ;
2013-03-12 17:56:23 +03:00
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 ;
2017-08-30 23:23:19 +02:00
logMod - > warn ( " Warning! Artifact rarity %s not recognized! " , className ) ;
2014-06-22 13:39:40 +03:00
return CArtifact : : ART_SPECIAL ;
}
2023-03-13 23:26:44 +02:00
void CArtHandler : : loadClass ( CArtifact * art , const JsonNode & node ) const
2014-06-22 13:39:40 +03:00
{
art - > aClass = stringToClass ( node [ " class " ] . String ( ) ) ;
2013-03-12 17:56:23 +03:00
}
2023-03-13 23:26:44 +02:00
void CArtHandler : : loadType ( CArtifact * art , const JsonNode & node ) const
2013-03-12 17:56:23 +03:00
{
2014-10-02 18:43:46 +03:00
# define ART_BEARER(x) { #x, ArtBearer::x },
static const std : : map < std : : string , int > artifactBearerMap = { ART_BEARER_LIST } ;
2013-03-12 17:56:23 +03:00
# 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
2017-08-30 23:23:19 +02:00
logMod - > warn ( " Warning! Artifact type %s not recognized! " , b . String ( ) ) ;
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
{
2023-03-13 23:26:44 +02:00
art - > constituents = std : : make_unique < std : : vector < CArtifact * > > ( ) ;
for ( const 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
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
art - > constituents - > push_back ( objects [ id ] ) ;
objects [ id ] - > constituentOf . push_back ( art ) ;
2013-03-02 19:55:51 +03:00
} ) ;
}
}
2012-12-10 16:55:54 +03:00
}
2023-03-13 23:26:44 +02:00
void CArtHandler : : loadGrowingArt ( CGrowingArtifact * art , const JsonNode & node ) const
2013-03-12 17:56:23 +03:00
{
2013-06-29 16:05:48 +03:00
for ( auto b : node [ " growing " ] [ " bonusesPerLevel " ] . Vector ( ) )
2013-03-12 17:56:23 +03:00
{
2023-03-13 23:26:44 +02:00
art - > bonusesPerLevel . emplace_back ( static_cast < ui16 > ( b [ " level " ] . Float ( ) ) , Bonus ( ) ) ;
2016-10-22 10:00:55 +02:00
JsonUtils : : parseBonus ( b [ " bonus " ] , & art - > bonusesPerLevel . back ( ) . second ) ;
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
{
2023-03-13 23:26:44 +02:00
art - > thresholdBonuses . emplace_back ( static_cast < ui16 > ( b [ " level " ] . Float ( ) ) , Bonus ( ) ) ;
2016-10-22 10:00:55 +02:00
JsonUtils : : parseBonus ( b [ " bonus " ] , & art - > thresholdBonuses . back ( ) . second ) ;
2013-03-12 17:56:23 +03: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 ;
2023-03-13 23:26:44 +02:00
out . emplace_back ( art ) ;
2014-06-22 13:39:40 +03:00
}
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 ) ;
2023-03-13 23:26:44 +02:00
if ( out . empty ( ) ) //no artifact of specified rarity, we need to take another one
2013-02-13 01:24:48 +03:00
{
getAllowedArts ( out , & treasures , CArtifact : : ART_TREASURE ) ;
getAllowedArts ( out , & minors , CArtifact : : ART_MINOR ) ;
getAllowedArts ( out , & majors , CArtifact : : ART_MAJOR ) ;
getAllowedArts ( out , & relics , CArtifact : : ART_RELIC ) ;
}
2023-03-13 23:26:44 +02:00
if ( out . empty ( ) ) //no arts are available at all
2013-02-13 01:24:48 +03:00
{
out . resize ( 64 ) ;
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
std : : fill_n ( out . begin ( ) , 64 , objects [ 2 ] ) ; //Give Grail - this can't be banned (hopefully)
2013-02-13 01:24:48 +03:00
}
} ;
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 )
{
2023-03-13 23:26:44 +02:00
return pickRandomArtifact ( rand , 0xff , std : : move ( accepts ) ) ;
2014-06-22 13:39:40 +03:00
}
ArtifactID CArtHandler : : pickRandomArtifact ( CRandomGenerator & rand , int flags )
{
2023-03-13 23:26:44 +02:00
return pickRandomArtifact ( rand , flags , [ ] ( const ArtifactID & ) { return true ; } ) ;
2014-06-22 13:39:40 +03:00
}
2017-07-15 13:08:20 +02:00
void CArtHandler : : makeItCreatureArt ( CArtifact * a , bool onlyCreature )
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
2017-07-15 13:08:20 +02:00
void CArtHandler : : makeItCommanderArt ( CArtifact * a , bool onlyCommander )
2012-12-27 14:00:28 +03:00
{
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
2023-03-13 23:26:44 +02:00
bool CArtHandler : : legalArtifact ( const ArtifactID & id )
2013-01-21 18:11:37 +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
auto art = objects [ id ] ;
2013-03-02 12:11:52 +03:00
//assert ( (!art->constituents) || art->constituents->size() ); //artifacts is not combined or has some components
2023-03-15 21:34:29 +02:00
if ( art - > constituents )
return false ; //no combo artifacts spawning
if ( art - > aClass < CArtifact : : ART_TREASURE | | art - > aClass > CArtifact : : ART_RELIC )
return false ; // invalid class
if ( ! art - > possibleSlots [ ArtBearer : : HERO ] . empty ( ) )
return true ;
if ( ! art - > possibleSlots [ ArtBearer : : CREATURE ] . empty ( ) & & VLC - > settings ( ) - > getBoolean ( EGameSettings : : MODULE_STACK_ARTIFACT ) )
return true ;
if ( ! art - > possibleSlots [ ArtBearer : : COMMANDER ] . empty ( ) & & VLC - > settings ( ) - > getBoolean ( EGameSettings : : MODULE_COMMANDERS ) )
return true ;
return false ;
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
{
2015-09-23 19:34:12 +02:00
//check artifacts allowed on a map
//TODO: This line will be different when custom map format is implemented
2013-01-21 18:11:37 +03:00
if ( allowed [ i ] & & legalArtifact ( i ) )
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
allowedArtifacts . push_back ( objects [ i ] ) ;
2010-08-18 12:50:25 +03:00
}
2023-03-13 23:26:44 +02:00
for ( ArtifactID i = ArtifactID : : ART_SELECTION ; i < ArtifactID ( static_cast < si32 > ( objects . size ( ) ) ) ; i . advance ( 1 ) ) //try to allow all artifacts added by mods
2012-12-14 11:37:46 +03:00
{
2013-03-02 12:11:52 +03:00
if ( legalArtifact ( ArtifactID ( i ) ) )
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
allowedArtifacts . push_back ( objects [ i ] ) ;
2012-12-27 14:00:28 +03:00
//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 ) ;
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
allowedArtifacts . resize ( size ( ) , true ) ;
2013-01-06 22:30:12 +03:00
return allowedArtifacts ;
}
2023-03-13 23:26:44 +02:00
void CArtHandler : : erasePickedArt ( const ArtifactID & id )
2013-02-19 01:37:22 +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
CArtifact * art = objects [ id ] ;
2013-02-19 01:37:22 +03:00
2023-04-16 23:41:50 +02:00
if ( ! ( art - > aClass & CArtifact : : ART_SPECIAL ) )
2013-02-19 01:37:22 +03:00
{
2023-04-16 23:41:50 +02:00
auto & artifactList = treasures ;
switch ( art - > aClass )
{
case CArtifact : : ART_MINOR :
artifactList = minors ;
break ;
case CArtifact : : ART_MAJOR :
artifactList = majors ;
break ;
case CArtifact : : ART_RELIC :
artifactList = relics ;
break ;
}
2023-04-16 19:42:56 +02:00
if ( artifactList . empty ( ) )
fillList ( artifactList , art - > aClass ) ;
2013-02-19 01:37:22 +03:00
2023-04-16 19:42:56 +02:00
auto itr = vstd : : find ( artifactList , art ) ;
if ( itr ! = artifactList . end ( ) )
2013-02-19 01:37:22 +03:00
{
2023-04-16 19:42:56 +02:00
artifactList . erase ( itr ) ;
2013-02-19 01:37:22 +03:00
}
else
2023-01-18 23:56:01 +02:00
logMod - > warn ( " Problem: cannot erase artifact %s from list, it was not present " , art - > getNameTranslated ( ) ) ;
2013-02-19 01:37:22 +03:00
}
else
2023-01-18 23:56:01 +02:00
logMod - > warn ( " Problem: cannot find list for artifact %s, strange class. (special?) " , art - > getNameTranslated ( ) ) ;
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.
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
for ( auto & art : objects )
2013-07-21 17:19:29 +03:00
{
for ( auto & bonus : art - > getExportedBonusList ( ) )
{
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
assert ( art = = objects [ art - > id ] ) ;
2013-07-21 17:19:29 +03:00
assert ( bonus - > source = = Bonus : : ARTIFACT ) ;
bonus - > sid = art - > id ;
}
}
2015-12-11 15:13:18 +02:00
CBonusSystemNode : : treeHasChanged ( ) ;
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 ;
2022-11-06 01:26:13 +02:00
attachTo ( * Art ) ;
2010-12-17 20:47:07 +02:00
}
std : : string CArtifactInstance : : nodeName ( ) const
{
2023-01-02 15:58:56 +02:00
return " Artifact instance of " + ( artType ? artType - > getJsonKey ( ) : std : : string ( " uninitialized " ) ) + " type " ;
2016-01-21 19:23:45 +02:00
}
2023-03-13 23:26:44 +02:00
CArtifactInstance * CArtifactInstance : : createScroll ( const SpellID & sid )
2010-12-17 20:47:07 +02:00
{
2023-03-13 23:26:44 +02:00
auto * ret = new CArtifactInstance ( VLC - > arth - > objects [ ArtifactID : : SPELL_SCROLL ] ) ;
2016-09-19 23:36:35 +02:00
auto b = std : : make_shared < Bonus > ( Bonus : : PERMANENT , Bonus : : SPELL , Bonus : : ARTIFACT_INSTANCE , - 1 , ArtifactID : : SPELL_SCROLL , sid ) ;
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
2023-04-13 19:40:36 +02:00
std : : string CArtifactInstance : : getDescription ( ) const
2016-01-21 19:23:45 +02:00
{
2023-01-21 15:58:28 +02:00
std : : string text = artType - > getDescriptionTranslated ( ) ;
2016-01-21 19:23:45 +02:00
if ( ! vstd : : contains ( text , ' { ' ) )
2023-01-02 15:58:56 +02:00
text = ' { ' + artType - > getNameTranslated ( ) + " } \n \n " + text ; //workaround for new artifacts with single name, turns it to H3-style
2016-01-21 19:23:45 +02:00
2023-01-02 15:58:56 +02:00
if ( artType - > getId ( ) = = ArtifactID : : SPELL_SCROLL )
2016-01-21 19:23:45 +02:00
{
// we expect scroll description to be like this: This scroll contains the [spell name] spell which is added into your spell book for as long as you carry the scroll.
// so we want to replace text in [...] with a spell name
// however other language versions don't have name placeholder at all, so we have to be careful
2023-04-13 19:40:36 +02:00
SpellID spellID = getScrollSpellID ( ) ;
2016-01-21 19:23:45 +02:00
size_t nameStart = text . find_first_of ( ' [ ' ) ;
size_t nameEnd = text . find_first_of ( ' ] ' , nameStart ) ;
2021-02-15 14:03:32 +02:00
if ( spellID . getNum ( ) > = 0 )
2016-01-21 19:23:45 +02:00
{
if ( nameStart ! = std : : string : : npos & & nameEnd ! = std : : string : : npos )
2023-01-02 00:06:42 +02:00
text = text . replace ( nameStart , nameEnd - nameStart + 1 , spellID . toSpell ( VLC - > spells ( ) ) - > getNameTranslated ( ) ) ;
2016-01-21 19:23:45 +02:00
}
}
return text ;
}
2023-03-21 12:13:53 +02:00
ArtifactID CArtifactInstance : : getTypeId ( ) const
2014-01-03 02:48:38 +03:00
{
2023-03-21 12:13:53 +02:00
return artType - > getId ( ) ;
2010-12-26 16:34:11 +02:00
}
2017-07-15 13:08:20 +02:00
bool CArtifactInstance : : canBePutAt ( const ArtifactLocation & al , bool assumeDestRemoved ) const
2010-12-26 16:34:11 +02:00
{
2023-03-13 12:28:33 +02:00
return artType - > canBePutAt ( al . getHolderArtSet ( ) , al . 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 ) ;
2022-12-30 21:43:32 +02:00
if ( ArtifactUtils : : isSlotEquipment ( al . slot ) )
2022-11-06 01:26:13 +02:00
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 ) ;
2022-12-30 21:43:32 +02:00
if ( ArtifactUtils : : isSlotEquipment ( al . slot ) )
2022-11-06 01:26:13 +02:00
al . getHolderNode ( ) - > detachFrom ( * this ) ;
2010-12-29 23:04:22 +02:00
}
bool CArtifactInstance : : canBeDisassembled ( ) const
{
2023-03-13 12:28:33 +02:00
return artType - > canBeDisassembled ( ) ;
2010-12-29 23:04:22 +02:00
}
2023-03-13 23:26:44 +02:00
void CArtifactInstance : : move ( const ArtifactLocation & src , const 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
{
2023-03-13 23:26:44 +02:00
auto * ret = new CArtifactInstance ( Art ) ;
2012-07-16 19:18:02 +03:00
if ( dynamic_cast < CGrowingArtifact * > ( Art ) )
{
2016-09-19 23:36:35 +02:00
auto bonus = std : : make_shared < 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
{
2023-03-13 23:26:44 +02: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
}
2023-03-13 23:26:44 +02:00
CArtifactInstance * CArtifactInstance : : createNewArtifactInstance ( const ArtifactID & aid )
2011-01-18 20:56:14 +02:00
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
return createNewArtifactInstance ( VLC - > arth - > objects [ aid ] ) ;
2011-01-18 20:56:14 +02:00
}
2023-03-13 23:26:44 +02:00
CArtifactInstance * CArtifactInstance : : createArtifact ( CMap * map , const ArtifactID & aid , int spellID )
2016-02-13 18:43:05 +02:00
{
CArtifactInstance * a = nullptr ;
if ( aid > = 0 )
{
if ( spellID < 0 )
{
a = CArtifactInstance : : createNewArtifactInstance ( aid ) ;
}
else
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
a = CArtifactInstance : : createScroll ( SpellID ( spellID ) ) ;
2016-02-13 18:43:05 +02:00
}
}
else //FIXME: create combined artifact instance for random combined artifacts, just in case
{
a = new CArtifactInstance ( ) ; //random, empty
}
map - > addNewArtifactInstance ( a ) ;
//TODO make it nicer
if ( a - > artType & & ( ! ! a - > artType - > constituents ) )
{
2023-03-13 23:26:44 +02:00
auto * comb = dynamic_cast < CCombinedArtifactInstance * > ( a ) ;
2016-02-13 18:43:05 +02:00
for ( CCombinedArtifactInstance : : ConstituentInfo & ci : comb - > constituentsInfo )
{
map - > addNewArtifactInstance ( ci . art ) ;
}
}
return a ;
}
2011-02-04 16:58:14 +02:00
void CArtifactInstance : : deserializationFix ( )
{
setType ( artType ) ;
}
2023-04-13 19:40:36 +02:00
SpellID CArtifactInstance : : getScrollSpellID ( ) const
2011-03-12 23:55:31 +02:00
{
2020-11-11 21:43:40 +02:00
const auto b = getBonusLocalFirst ( Selector : : type ( ) ( Bonus : : SPELL ) ) ;
2011-03-12 23:55:31 +02:00
if ( ! b )
{
2017-08-30 23:23:19 +02:00
logMod - > warn ( " Warning: %s doesn't bear any spell! " , nodeName ( ) ) ;
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 ;
}
2011-01-18 20:56:14 +02:00
CCombinedArtifactInstance : : CCombinedArtifactInstance ( CArtifact * Art )
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
: CArtifactInstance ( Art ) //TODO: seems unused, but need to be written
2011-01-18 20:56:14 +02:00
{
}
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
{
2023-01-02 15:58:56 +02:00
addAsConstituent ( CArtifactInstance : : createNewArtifactInstance ( art - > getId ( ) ) , ArtifactPosition : : PRE_FIRST ) ;
2011-01-22 05:43:20 +02:00
}
}
2023-03-13 23:26:44 +02:00
void CCombinedArtifactInstance : : addAsConstituent ( CArtifactInstance * art , const ArtifactPosition & slot )
2011-01-22 05:43:20 +02:00
{
2022-12-18 14:33:59 +02:00
assert ( vstd : : contains_if ( * artType - > constituents , [ = ] ( const CArtifact * constituent ) {
2023-01-02 15:58:56 +02:00
return constituent - > getId ( ) = = art - > artType - > getId ( ) ;
2022-12-18 14:33:59 +02:00
} ) ) ;
2011-07-13 21:39:02 +03:00
assert ( art - > getParentNodes ( ) . size ( ) = = 1 & & art - > getParentNodes ( ) . front ( ) = = art - > artType ) ;
2023-03-13 23:26:44 +02:00
constituentsInfo . emplace_back ( art , slot ) ;
2022-11-06 01:26:13 +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
{
2022-12-30 21:43:32 +02:00
if ( al . slot = = ArtifactPosition : : TRANSITION_POS )
{
CArtifactInstance : : putAt ( al ) ;
}
else if ( ArtifactUtils : : isSlotBackpack ( al . slot ) )
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
2023-03-18 22:58:39 +02: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 ) ;
2023-03-18 22:58:39 +02:00
if ( ! ( inActiveSlot & & suggestedPosValid ) ) //there is a valid suggestion where to place lock
2023-03-21 12:13:53 +02:00
ci . slot = ArtifactUtils : : getArtAnyPosition ( al . getHolderArtSet ( ) , ci . art - > getTypeId ( ) ) ;
2011-01-22 05:43:20 +02:00
2023-03-18 22:58:39 +02:00
assert ( ArtifactUtils : : isSlotEquipment ( ci . slot ) ) ;
al . getHolderArtSet ( ) - > setNewArtSlot ( ci . slot , 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
{
2022-12-30 21:43:32 +02:00
if ( ArtifactUtils : : isSlotBackpack ( al . slot ) | | al . slot = = ArtifactPosition : : TRANSITION_POS )
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
}
}
2023-03-13 23:26:44 +02: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 )
2022-11-06 01:26:13 +02:00
attachTo ( * ci . art ) ;
2011-02-04 16:58:14 +02:00
}
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 ;
}
2023-03-13 23:26:44 +02:00
CCombinedArtifactInstance : : ConstituentInfo : : ConstituentInfo ( CArtifactInstance * Art , const ArtifactPosition & Slot ) :
art ( Art ) ,
slot ( Slot )
2011-01-18 20:56:14 +02:00
{
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
2016-11-13 12:38:42 +02:00
CArtifactSet : : ~ CArtifactSet ( ) = default ;
2023-03-13 23:26:44 +02:00
const CArtifactInstance * CArtifactSet : : getArt ( const ArtifactPosition & pos , bool excludeLocked ) 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
}
2023-03-13 23:26:44 +02:00
CArtifactInstance * CArtifactSet : : getArt ( const ArtifactPosition & pos , bool excludeLocked )
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
}
2023-03-13 23:26:44 +02:00
ArtifactPosition CArtifactSet : : getArtPos ( const ArtifactID & aid , bool onlyWorn , bool allowLocked ) const
2011-06-24 20:43:02 +03:00
{
2022-10-01 08:28:32 +02:00
const auto result = getAllArtPositions ( aid , onlyWorn , allowLocked , false ) ;
return result . empty ( ) ? ArtifactPosition { ArtifactPosition : : PRE_FIRST } : result [ 0 ] ;
}
2023-03-13 23:26:44 +02:00
ArtifactPosition CArtifactSet : : getArtBackpackPos ( const ArtifactID & aid ) const
2022-11-19 16:09:32 +02:00
{
const auto result = getBackpackArtPositions ( aid ) ;
return result . empty ( ) ? ArtifactPosition { ArtifactPosition : : PRE_FIRST } : result [ 0 ] ;
}
2023-03-13 23:26:44 +02:00
std : : vector < ArtifactPosition > CArtifactSet : : getAllArtPositions ( const ArtifactID & aid , bool onlyWorn , bool allowLocked , bool getAll ) const
2022-10-01 08:28:32 +02:00
{
std : : vector < ArtifactPosition > result ;
2023-03-13 23:26:44 +02:00
for ( const auto & slotInfo : artifactsWorn )
2023-03-21 12:13:53 +02:00
if ( slotInfo . second . artifact - > getTypeId ( ) = = aid & & ( allowLocked | | ! slotInfo . second . locked ) )
2022-11-17 19:43:54 +02:00
result . push_back ( slotInfo . first ) ;
2011-06-24 20:43:02 +03:00
if ( onlyWorn )
2022-10-01 08:28:32 +02:00
return result ;
if ( ! getAll & & ! result . empty ( ) )
return result ;
2011-06-24 20:43:02 +03:00
2022-11-17 19:43:54 +02:00
auto backpackPositions = getBackpackArtPositions ( aid ) ;
result . insert ( result . end ( ) , backpackPositions . begin ( ) , backpackPositions . end ( ) ) ;
return result ;
}
2023-03-13 23:26:44 +02:00
std : : vector < ArtifactPosition > CArtifactSet : : getBackpackArtPositions ( const ArtifactID & aid ) const
2022-11-17 19:43:54 +02:00
{
std : : vector < ArtifactPosition > result ;
2011-06-24 20:43:02 +03:00
2022-11-17 19:43:54 +02:00
si32 backpackPosition = GameConstants : : BACKPACK_START ;
2023-03-13 23:26:44 +02:00
for ( const auto & artInfo : artifactsInBackpack )
2022-11-17 19:43:54 +02:00
{
2023-03-13 23:26:44 +02:00
const auto * art = artInfo . getArt ( ) ;
2023-01-02 15:58:56 +02:00
if ( art & & art - > artType - > getId ( ) = = aid )
2022-11-18 22:15:03 +02:00
result . emplace_back ( backpackPosition ) ;
2022-11-17 19:43:54 +02:00
backpackPosition + + ;
}
2022-10-01 08:28:32 +02:00
return result ;
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
}
2023-03-13 23:26:44 +02:00
const CArtifactInstance * CArtifactSet : : getArtByInstanceId ( const 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
}
2023-03-13 23:26:44 +02:00
bool CArtifactSet : : hasArt ( const ArtifactID & aid , bool onlyWorn , bool searchBackpackAssemblies , bool allowLocked ) const
2012-04-14 05:20:22 +03:00
{
2022-10-01 08:28:32 +02:00
return getArtPosCount ( aid , onlyWorn , searchBackpackAssemblies , allowLocked ) > 0 ;
}
2023-03-13 23:26:44 +02:00
bool CArtifactSet : : hasArtBackpack ( const ArtifactID & aid ) const
2022-11-17 19:43:54 +02:00
{
2023-03-13 23:26:44 +02:00
return ! getBackpackArtPositions ( aid ) . empty ( ) ;
2022-11-17 19:43:54 +02:00
}
2023-03-13 23:26:44 +02:00
unsigned CArtifactSet : : getArtPosCount ( const ArtifactID & aid , bool onlyWorn , bool searchBackpackAssemblies , bool allowLocked ) const
2022-10-01 08:28:32 +02:00
{
const auto allPositions = getAllArtPositions ( aid , onlyWorn , allowLocked , true ) ;
if ( ! allPositions . empty ( ) )
return allPositions . size ( ) ;
if ( searchBackpackAssemblies & & getHiddenArt ( aid ) )
return 1 ;
return 0 ;
2016-01-22 11:53:01 +02:00
}
2023-03-13 23:26:44 +02:00
std : : pair < const CCombinedArtifactInstance * , const CArtifactInstance * > CArtifactSet : : searchForConstituent ( const ArtifactID & aid ) const
2016-01-22 11:53:01 +02:00
{
2023-03-13 23:26:44 +02:00
for ( const auto & slot : artifactsInBackpack )
2016-01-22 11:53:01 +02:00
{
auto art = slot . artifact ;
if ( art - > canBeDisassembled ( ) )
{
2023-03-13 23:26:44 +02:00
auto * ass = dynamic_cast < CCombinedArtifactInstance * > ( art . get ( ) ) ;
2016-01-22 11:53:01 +02:00
for ( auto & ci : ass - > constituentsInfo )
{
2023-03-21 12:13:53 +02:00
if ( ci . art - > getTypeId ( ) = = aid )
2016-01-22 11:53:01 +02:00
{
return { ass , ci . art } ;
}
}
}
}
return { nullptr , nullptr } ;
}
2023-03-13 23:26:44 +02:00
const CArtifactInstance * CArtifactSet : : getHiddenArt ( const ArtifactID & aid ) const
2016-01-22 11:53:01 +02:00
{
return searchForConstituent ( aid ) . second ;
}
2023-03-13 23:26:44 +02:00
const CCombinedArtifactInstance * CArtifactSet : : getAssemblyByConstituent ( const ArtifactID & aid ) const
2012-04-14 05:20:22 +03:00
{
2016-01-22 11:53:01 +02:00
return searchForConstituent ( aid ) . first ;
2012-04-14 05:20:22 +03:00
}
2023-03-13 23:26:44 +02:00
const ArtSlotInfo * CArtifactSet : : getSlot ( const ArtifactPosition & pos ) const
2014-01-03 02:48:38 +03:00
{
2022-12-28 21:58:32 +02:00
if ( pos = = ArtifactPosition : : TRANSITION_POS )
2022-12-29 20:39:01 +02:00
{
// Always add to the end. Always take from the beginning.
2023-02-10 13:46:34 +02:00
if ( artifactsTransitionPos . empty ( ) )
return nullptr ;
else
return & ( * artifactsTransitionPos . begin ( ) ) ;
2022-12-29 20:39:01 +02:00
}
2014-01-03 02:48:38 +03:00
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
}
2023-03-13 23:26:44 +02:00
bool CArtifactSet : : isPositionFree ( const ArtifactPosition & pos , bool onlyLockCheck ) 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
}
2023-03-13 23:26:44 +02:00
ArtSlotInfo & CArtifactSet : : retrieveNewArtSlot ( const ArtifactPosition & slot )
2011-06-24 20:43:02 +03:00
{
assert ( ! vstd : : contains ( artifactsWorn , slot ) ) ;
2022-12-28 21:58:32 +02:00
if ( slot = = ArtifactPosition : : TRANSITION_POS )
2022-12-29 20:39:01 +02:00
{
// Always add to the end. Always take from the beginning.
2023-03-13 23:26:44 +02:00
artifactsTransitionPos . emplace_back ( ) ;
2022-12-29 20:39:01 +02:00
return artifactsTransitionPos . back ( ) ;
}
2022-12-28 21:58:32 +02:00
if ( ! ArtifactUtils : : isSlotBackpack ( slot ) )
2022-12-18 14:33:59 +02:00
return artifactsWorn [ slot ] ;
ArtSlotInfo newSlot ;
size_t index = slot - GameConstants : : BACKPACK_START ;
auto position = artifactsInBackpack . begin ( ) + index ;
auto inserted = artifactsInBackpack . insert ( position , newSlot ) ;
return * inserted ;
2011-06-24 20:43:02 +03:00
}
2023-03-13 23:26:44 +02:00
void CArtifactSet : : setNewArtSlot ( const ArtifactPosition & slot , CArtifactInstance * art , bool locked )
2012-04-14 05:20:22 +03:00
{
2018-02-10 20:52:23 +02:00
ArtSlotInfo & asi = retrieveNewArtSlot ( slot ) ;
2012-04-14 05:20:22 +03:00
asi . artifact = art ;
asi . locked = locked ;
}
2023-03-13 23:26:44 +02:00
void CArtifactSet : : eraseArtSlot ( const ArtifactPosition & slot )
2011-06-24 20:43:02 +03:00
{
2022-12-29 20:39:01 +02:00
if ( slot = = ArtifactPosition : : TRANSITION_POS )
{
assert ( ! artifactsTransitionPos . empty ( ) ) ;
artifactsTransitionPos . erase ( artifactsTransitionPos . begin ( ) ) ;
}
else if ( ArtifactUtils : : isSlotBackpack ( slot ) )
2011-06-24 20:43:02 +03:00
{
2022-12-18 14:33:59 +02:00
auto backpackSlot = ArtifactPosition ( slot - GameConstants : : BACKPACK_START ) ;
assert ( artifactsInBackpack . begin ( ) + backpackSlot < artifactsInBackpack . end ( ) ) ;
artifactsInBackpack . erase ( artifactsInBackpack . begin ( ) + backpackSlot ) ;
2011-06-24 20:43:02 +03:00
}
else
{
2022-11-29 01:20:31 +02:00
artifactsWorn . erase ( slot ) ;
2011-06-24 20:43:02 +03:00
}
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 )
2022-11-06 01:26:13 +02:00
node - > attachTo ( * elem . second . artifact ) ;
2012-04-14 19:28:36 +03:00
}
2016-01-24 01:27:14 +02:00
2016-11-13 12:38:42 +02:00
void CArtifactSet : : serializeJsonArtifacts ( JsonSerializeFormat & handler , const std : : string & fieldName , CMap * map )
{
//todo: creature and commander artifacts
if ( handler . saving & & artifactsInBackpack . empty ( ) & & artifactsWorn . empty ( ) )
return ;
if ( ! handler . saving )
{
assert ( map ) ;
artifactsInBackpack . clear ( ) ;
artifactsWorn . clear ( ) ;
}
auto s = handler . enterStruct ( fieldName ) ;
switch ( bearerType ( ) )
{
case ArtBearer : : HERO :
serializeJsonHero ( handler , map ) ;
break ;
case ArtBearer : : CREATURE :
serializeJsonCreature ( handler , map ) ;
break ;
case ArtBearer : : COMMANDER :
serializeJsonCommander ( handler , map ) ;
break ;
default :
assert ( false ) ;
break ;
}
}
void CArtifactSet : : serializeJsonHero ( JsonSerializeFormat & handler , CMap * map )
{
for ( ArtifactPosition ap = ArtifactPosition : : HEAD ; ap < ArtifactPosition : : AFTER_LAST ; ap . advance ( 1 ) )
{
serializeJsonSlot ( handler , ap , map ) ;
}
std : : vector < ArtifactID > backpackTemp ;
if ( handler . saving )
{
backpackTemp . reserve ( artifactsInBackpack . size ( ) ) ;
for ( const ArtSlotInfo & info : artifactsInBackpack )
2023-03-21 12:13:53 +02:00
backpackTemp . push_back ( info . artifact - > getTypeId ( ) ) ;
2016-11-13 12:38:42 +02:00
}
2017-07-20 06:08:49 +02:00
handler . serializeIdArray ( NArtifactPosition : : backpack , backpackTemp ) ;
2016-11-13 12:38:42 +02:00
if ( ! handler . saving )
{
2023-01-02 15:58:56 +02:00
for ( const ArtifactID & artifactID : backpackTemp )
2016-11-13 12:38:42 +02:00
{
2023-03-13 23:26:44 +02:00
auto * artifact = CArtifactInstance : : createArtifact ( map , artifactID . toEnum ( ) ) ;
2023-03-13 12:28:33 +02:00
auto slot = ArtifactPosition ( GameConstants : : BACKPACK_START + ( si32 ) artifactsInBackpack . size ( ) ) ;
if ( artifact - > artType - > canBePutAt ( this , slot ) )
2016-11-13 12:38:42 +02:00
putArtifact ( slot , artifact ) ;
}
}
}
void CArtifactSet : : serializeJsonCreature ( JsonSerializeFormat & handler , CMap * map )
2016-01-24 01:27:14 +02:00
{
2016-11-13 12:38:42 +02:00
logGlobal - > error ( " CArtifactSet::serializeJsonCreature not implemented " ) ;
}
2016-01-24 01:27:14 +02:00
2016-11-13 12:38:42 +02:00
void CArtifactSet : : serializeJsonCommander ( JsonSerializeFormat & handler , CMap * map )
{
logGlobal - > error ( " CArtifactSet::serializeJsonCommander not implemented " ) ;
2016-01-24 01:27:14 +02:00
}
2016-11-13 12:38:42 +02:00
void CArtifactSet : : serializeJsonSlot ( JsonSerializeFormat & handler , const ArtifactPosition & slot , CMap * map )
2016-01-24 01:27:14 +02:00
{
2016-11-13 12:38:42 +02:00
ArtifactID artifactID ;
if ( handler . saving )
{
const ArtSlotInfo * info = getSlot ( slot ) ;
if ( info ! = nullptr & & ! info - > locked )
{
2023-03-21 12:13:53 +02:00
artifactID = info - > artifact - > getTypeId ( ) ;
2017-07-20 06:08:49 +02:00
handler . serializeId ( NArtifactPosition : : namesHero [ slot . num ] , artifactID , ArtifactID : : NONE ) ;
2016-11-13 12:38:42 +02:00
}
}
else
{
2017-07-20 06:08:49 +02:00
handler . serializeId ( NArtifactPosition : : namesHero [ slot . num ] , artifactID , ArtifactID : : NONE ) ;
2016-01-24 01:27:14 +02:00
2016-11-13 12:38:42 +02:00
if ( artifactID ! = ArtifactID : : NONE )
{
2023-03-13 23:26:44 +02:00
auto * artifact = CArtifactInstance : : createArtifact ( map , artifactID . toEnum ( ) ) ;
2016-11-13 12:38:42 +02:00
2023-03-13 12:28:33 +02:00
if ( artifact - > artType - > canBePutAt ( this , slot ) )
2016-11-13 12:38:42 +02:00
{
putArtifact ( slot , artifact ) ;
}
else
{
2017-08-10 18:39:27 +02:00
logGlobal - > debug ( " Artifact can't be put at the specified location. " ) ; //TODO add more debugging information
2016-11-13 12:38:42 +02:00
}
}
}
2016-01-24 01:27:14 +02:00
}
2022-07-26 15:07:42 +02:00
2023-03-13 23:26:44 +02:00
CArtifactFittingSet : : CArtifactFittingSet ( ArtBearer : : ArtBearer Bearer ) :
Bearer ( Bearer )
2022-11-06 23:29:22 +02:00
{
}
2022-11-10 18:29:39 +02:00
void CArtifactFittingSet : : putArtifact ( ArtifactPosition pos , CArtifactInstance * art )
2022-11-06 23:29:22 +02:00
{
2023-02-11 13:21:45 +02:00
if ( art & & art - > canBeDisassembled ( ) & & ArtifactUtils : : isSlotEquipment ( pos ) )
2022-11-06 23:29:22 +02:00
{
2022-11-10 18:29:39 +02:00
for ( auto & part : dynamic_cast < CCombinedArtifactInstance * > ( art ) - > constituentsInfo )
2022-11-06 23:29:22 +02:00
{
2023-03-21 12:13:53 +02:00
const auto slot = ArtifactUtils : : getArtAnyPosition ( this , part . art - > getTypeId ( ) ) ;
2023-03-18 22:58:39 +02:00
assert ( slot ! = ArtifactPosition : : PRE_FIRST ) ;
2022-11-06 23:29:22 +02:00
// For the ArtFittingSet is no needed to do figureMainConstituent, just lock slots
2023-03-18 22:58:39 +02:00
this - > setNewArtSlot ( slot , part . art , true ) ;
2022-11-06 23:29:22 +02:00
}
}
else
{
this - > setNewArtSlot ( pos , art , false ) ;
}
}
2023-03-13 12:28:33 +02:00
void CArtifactFittingSet : : removeArtifact ( ArtifactPosition pos )
{
// Removes the art from the CartifactSet, but does not remove it from art->constituentsInfo.
// removeArtifact is for CArtifactFittingSet only. Do not move it to the parent class.
auto art = getArt ( pos ) ;
if ( art = = nullptr )
return ;
if ( art - > canBeDisassembled ( ) )
{
auto combinedArt = dynamic_cast < CCombinedArtifactInstance * > ( art ) ;
for ( const auto & part : combinedArt - > constituentsInfo )
{
if ( ArtifactUtils : : isSlotEquipment ( part . slot ) )
eraseArtSlot ( part . slot ) ;
}
}
eraseArtSlot ( pos ) ;
}
2022-11-06 23:29:22 +02:00
ArtBearer : : ArtBearer CArtifactFittingSet : : bearerType ( ) const
{
return this - > Bearer ;
}
2023-03-20 01:18:32 +02:00
DLL_LINKAGE ArtifactPosition ArtifactUtils : : getArtAnyPosition ( const CArtifactSet * target , const ArtifactID & aid )
2022-11-06 23:29:22 +02:00
{
2023-03-13 12:28:33 +02:00
const auto * art = aid . toArtifact ( ) ;
for ( const auto & slot : art - > possibleSlots . at ( target - > bearerType ( ) ) )
2022-11-06 23:29:22 +02:00
{
2023-03-18 12:44:01 +02:00
if ( art - > canBePutAt ( target , slot ) )
2022-11-06 23:29:22 +02:00
return slot ;
}
2023-03-20 01:18:32 +02:00
return getArtBackpackPosition ( target , aid ) ;
}
DLL_LINKAGE ArtifactPosition ArtifactUtils : : getArtBackpackPosition ( const CArtifactSet * target , const ArtifactID & aid )
{
const auto * art = aid . toArtifact ( ) ;
2023-03-18 12:44:01 +02:00
if ( art - > canBePutAt ( target , GameConstants : : BACKPACK_START ) )
{
return GameConstants : : BACKPACK_START ;
}
return ArtifactPosition : : PRE_FIRST ;
2022-11-06 23:29:22 +02:00
}
2022-11-30 17:57:39 +02:00
DLL_LINKAGE const std : : vector < ArtifactPosition : : EArtifactPosition > & ArtifactUtils : : unmovableSlots ( )
{
2022-12-02 21:37:58 +02:00
static const std : : vector < ArtifactPosition : : EArtifactPosition > positions =
2022-11-30 17:57:39 +02:00
{
ArtifactPosition : : SPELLBOOK ,
ArtifactPosition : : MACH4
} ;
2022-12-02 21:37:58 +02:00
return positions ;
2022-11-30 17:57:39 +02:00
}
DLL_LINKAGE const std : : vector < ArtifactPosition : : EArtifactPosition > & ArtifactUtils : : constituentWornSlots ( )
{
2022-12-02 21:37:58 +02:00
static const std : : vector < ArtifactPosition : : EArtifactPosition > positions =
2022-11-30 17:57:39 +02:00
{
ArtifactPosition : : HEAD ,
ArtifactPosition : : SHOULDERS ,
ArtifactPosition : : NECK ,
ArtifactPosition : : RIGHT_HAND ,
ArtifactPosition : : LEFT_HAND ,
ArtifactPosition : : TORSO ,
ArtifactPosition : : RIGHT_RING ,
ArtifactPosition : : LEFT_RING ,
ArtifactPosition : : FEET ,
ArtifactPosition : : MISC1 ,
ArtifactPosition : : MISC2 ,
ArtifactPosition : : MISC3 ,
ArtifactPosition : : MISC4 ,
ArtifactPosition : : MISC5 ,
} ;
2022-12-02 21:37:58 +02:00
return positions ;
2022-11-30 17:57:39 +02:00
}
2022-11-29 20:46:14 +02:00
DLL_LINKAGE bool ArtifactUtils : : isArtRemovable ( const std : : pair < ArtifactPosition , ArtSlotInfo > & slot )
2022-11-06 23:29:22 +02:00
{
return slot . second . artifact
& & ! slot . second . locked
2022-11-30 17:57:39 +02:00
& & ! vstd : : contains ( unmovableSlots ( ) , slot . first ) ;
2022-11-06 23:29:22 +02:00
}
2023-03-13 23:26:44 +02:00
DLL_LINKAGE bool ArtifactUtils : : checkSpellbookIsNeeded ( const CGHeroInstance * heroPtr , const ArtifactID & artID , const ArtifactPosition & slot )
2022-11-07 00:18:05 +02:00
{
// TODO what'll happen if Titan's thunder is equipped by pickin git up or the start of game?
// Titan's Thunder creates new spellbook on equip
2022-11-10 18:29:39 +02:00
if ( artID = = ArtifactID : : TITANS_THUNDER & & slot = = ArtifactPosition : : RIGHT_HAND )
2022-11-07 00:18:05 +02:00
{
2022-11-10 18:29:39 +02:00
if ( heroPtr )
2022-11-07 00:18:05 +02:00
{
2022-11-10 18:29:39 +02:00
if ( heroPtr & & ! heroPtr - > hasSpellbook ( ) )
2022-11-07 00:18:05 +02:00
return true ;
}
}
return false ;
}
2023-03-13 23:26:44 +02:00
DLL_LINKAGE bool ArtifactUtils : : isSlotBackpack ( const ArtifactPosition & slot )
2022-11-18 22:49:57 +02:00
{
return slot > = GameConstants : : BACKPACK_START ;
}
2023-03-13 23:26:44 +02:00
DLL_LINKAGE bool ArtifactUtils : : isSlotEquipment ( const ArtifactPosition & slot )
2022-12-30 21:43:32 +02:00
{
return slot < GameConstants : : BACKPACK_START & & slot > = 0 ;
}
2023-03-18 12:44:01 +02:00
DLL_LINKAGE bool ArtifactUtils : : isBackpackFreeSlots ( const CArtifactSet * target , const size_t reqSlots )
{
const auto backpackCap = VLC - > settings ( ) - > getInteger ( EGameSettings : : HEROES_BACKPACK_CAP ) ;
if ( backpackCap < 0 )
return true ;
else
return target - > artifactsInBackpack . size ( ) + reqSlots < = backpackCap ;
}
2023-04-13 19:40:36 +02:00
DLL_LINKAGE std : : vector < const CArtifact * > ArtifactUtils : : assemblyPossibilities (
const CArtifactSet * artSet , const ArtifactID & aid , bool equipped )
{
std : : vector < const CArtifact * > arts ;
const auto * art = aid . toArtifact ( ) ;
if ( art - > canBeDisassembled ( ) )
return arts ;
for ( const auto artifact : art - > constituentOf )
{
assert ( artifact - > constituents ) ;
bool possible = true ;
for ( const auto constituent : * artifact - > constituents ) //check if all constituents are available
{
if ( equipped )
{
// Search for equipped arts
if ( ! artSet - > hasArt ( constituent - > getId ( ) , true , false , false ) )
{
possible = false ;
break ;
}
}
else
{
// Search in backpack
if ( ! artSet - > hasArtBackpack ( constituent - > getId ( ) ) )
{
possible = false ;
break ;
}
}
}
if ( possible )
arts . push_back ( artifact ) ;
}
return arts ;
}
2022-07-26 15:07:42 +02:00
VCMI_LIB_NAMESPACE_END