2017-07-13 10:26:03 +02:00
/*
* CHeroHandler . 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-08 17:58:04 +03:00
# include "CHeroHandler.h"
2011-12-14 00:23:17 +03:00
2012-08-25 11:44:51 +03:00
# include "CGeneralTextHandler.h"
2013-07-28 17:49:50 +03:00
# include "filesystem/Filesystem.h"
2012-08-25 11:44:51 +03:00
# include "VCMI_Lib.h"
# include "JsonNode.h"
2012-12-14 18:32:53 +03:00
# include "StringConstants.h"
2017-06-24 16:42:05 +02:00
# include "battle/BattleHex.h"
2013-12-13 21:27:54 +03:00
# include "CCreatureHandler.h"
2012-12-03 19:00:17 +03:00
# include "CModHandler.h"
2012-12-15 11:47:02 +03:00
# include "CTownHandler.h"
2022-06-20 16:39:50 +02:00
# include "Terrain.h"
2014-06-05 14:19:47 +03:00
# include "mapObjects/CObjectHandler.h" //for hero specialty
2018-03-31 07:56:40 +02:00
# include "CSkillHandler.h"
2013-11-10 00:29:46 +03:00
# include <math.h>
2009-08-31 18:57:15 +03:00
2014-06-05 19:52:14 +03:00
# include "mapObjects/CObjectClassesHandler.h"
2022-06-28 10:05:30 +02:00
# include "BattleFieldHandler.h"
2014-06-05 19:52:14 +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
CHero : : CHero ( ) = default ;
CHero : : ~ CHero ( ) = default ;
int32_t CHero : : getIndex ( ) const
{
return ID . getNum ( ) ;
}
int32_t CHero : : getIconIndex ( ) const
{
return imageIndex ;
}
const std : : string & CHero : : getName ( ) const
{
return name ;
}
const std : : string & CHero : : getJsonKey ( ) const
{
return identifier ;
}
HeroTypeID CHero : : getId ( ) const
{
return ID ;
}
void CHero : : registerIcons ( const IconRegistar & cb ) const
{
cb ( getIconIndex ( ) , " UN32 " , iconSpecSmall ) ;
cb ( getIconIndex ( ) , " UN44 " , iconSpecLarge ) ;
cb ( getIconIndex ( ) , " PORTRAITSLARGE " , portraitLarge ) ;
cb ( getIconIndex ( ) , " PORTRAITSSMALL " , portraitSmall ) ;
}
void CHero : : updateFrom ( const JsonNode & data )
{
//todo: CHero::updateFrom
}
void CHero : : serializeJson ( JsonSerializeFormat & handler )
{
}
2014-04-10 20:11:09 +03:00
SecondarySkill CHeroClass : : chooseSecSkill ( const std : : set < SecondarySkill > & possibles , CRandomGenerator & rand ) const //picks secondary skill out from given possibilities
2008-08-04 18:56:36 +03:00
{
int totalProb = 0 ;
2013-06-29 16:05:48 +03:00
for ( auto & possible : possibles )
2008-08-04 18:56:36 +03:00
{
2013-06-29 16:05:48 +03:00
totalProb + = secSkillProbability [ possible ] ;
2008-08-04 18:56:36 +03:00
}
2013-09-05 02:00:51 +03:00
if ( totalProb ! = 0 ) // may trigger if set contains only banned skills (0 probability)
2008-08-04 18:56:36 +03:00
{
2014-04-10 20:11:09 +03:00
auto ran = rand . nextInt ( totalProb - 1 ) ;
2013-09-05 02:00:51 +03:00
for ( auto & possible : possibles )
{
ran - = secSkillProbability [ possible ] ;
2014-04-10 20:11:09 +03:00
if ( ran < 0 )
{
2013-09-05 02:00:51 +03:00
return possible ;
2014-04-10 20:11:09 +03:00
}
2013-09-05 02:00:51 +03:00
}
2008-08-04 18:56:36 +03:00
}
2013-09-05 02:00:51 +03:00
// FIXME: select randomly? How H3 handles such rare situation?
return * possibles . begin ( ) ;
2008-08-04 18:56:36 +03:00
}
2013-09-09 18:23:59 +03:00
bool CHeroClass : : isMagicHero ( ) const
{
2013-12-13 21:27:54 +03:00
return affinity = = MAGIC ;
2013-09-09 18:23:59 +03:00
}
2012-09-23 21:01:04 +03:00
EAlignment : : EAlignment CHeroClass : : getAlignment ( ) const
2010-07-20 09:05:45 +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
return EAlignment : : EAlignment ( ( * VLC - > townh ) [ faction ] - > alignment ) ;
}
int32_t CHeroClass : : getIndex ( ) const
{
return id . getNum ( ) ;
}
int32_t CHeroClass : : getIconIndex ( ) const
{
return getIndex ( ) ;
}
const std : : string & CHeroClass : : getName ( ) const
{
return name ;
}
const std : : string & CHeroClass : : getJsonKey ( ) const
{
return identifier ;
}
HeroClassID CHeroClass : : getId ( ) const
{
return id ;
}
void CHeroClass : : registerIcons ( const IconRegistar & cb ) const
{
}
void CHeroClass : : updateFrom ( const JsonNode & data )
{
//TODO: CHeroClass::updateFrom
}
void CHeroClass : : serializeJson ( JsonSerializeFormat & handler )
{
2010-07-20 09:05:45 +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
2014-01-06 20:45:21 +03:00
CHeroClass : : CHeroClass ( )
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
: faction ( 0 ) , id ( ) , affinity ( 0 ) , defaultTavernChance ( 0 ) , commander ( nullptr )
2014-01-06 20:45:21 +03:00
{
}
2021-02-12 23:24:14 +02:00
void CHeroClassHandler : : fillPrimarySkillData ( const JsonNode & node , CHeroClass * heroClass , PrimarySkill : : PrimarySkill pSkill )
{
const auto & skillName = PrimarySkill : : names [ pSkill ] ;
auto currentPrimarySkillValue = ( int ) node [ " primarySkills " ] [ skillName ] . Integer ( ) ;
//minimal value is 0 for attack and defense and 1 for spell power and knowledge
auto primarySkillLegalMinimum = ( pSkill = = PrimarySkill : : ATTACK | | pSkill = = PrimarySkill : : DEFENSE ) ? 0 : 1 ;
if ( currentPrimarySkillValue < primarySkillLegalMinimum )
{
logMod - > error ( " Hero class '%s' has incorrect initial value '%d' for skill '%s'. Value '%d' will be used instead. " ,
heroClass - > identifier , currentPrimarySkillValue , skillName , primarySkillLegalMinimum ) ;
currentPrimarySkillValue = primarySkillLegalMinimum ;
}
heroClass - > primarySkillInitial . push_back ( currentPrimarySkillValue ) ;
heroClass - > primarySkillLowLevel . push_back ( ( int ) node [ " lowLevelChance " ] [ skillName ] . Float ( ) ) ;
heroClass - > primarySkillHighLevel . push_back ( ( int ) node [ " highLevelChance " ] [ skillName ] . Float ( ) ) ;
}
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 > & CHeroClassHandler : : getTypeNames ( ) const
{
static const std : : vector < std : : string > typeNames = { " heroClass " } ;
return typeNames ;
}
CHeroClass * CHeroClassHandler : : loadFromJson ( const std : : string & scope , const JsonNode & node , const std : : string & identifier , size_t index )
2009-01-11 00:08:18 +02:00
{
2013-12-13 21:27:54 +03:00
std : : string affinityStr [ 2 ] = { " might " , " magic " } ;
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 heroClass = new CHeroClass ( ) ;
heroClass - > id = HeroClassID ( index ) ;
2015-08-24 10:55:45 +02:00
heroClass - > identifier = identifier ;
2013-04-21 15:49:26 +03:00
heroClass - > imageBattleFemale = node [ " animation " ] [ " battle " ] [ " female " ] . String ( ) ;
heroClass - > imageBattleMale = node [ " animation " ] [ " battle " ] [ " male " ] . String ( ) ;
2014-06-16 19:27:26 +03:00
//MODS COMPATIBILITY FOR 0.96
2013-04-21 15:49:26 +03:00
heroClass - > imageMapFemale = node [ " animation " ] [ " map " ] [ " female " ] . String ( ) ;
heroClass - > imageMapMale = node [ " animation " ] [ " map " ] [ " male " ] . String ( ) ;
heroClass - > name = node [ " name " ] . String ( ) ;
2013-12-13 21:27:54 +03:00
heroClass - > affinity = vstd : : find_pos ( affinityStr , node [ " affinity " ] . String ( ) ) ;
2013-04-21 15:49:26 +03:00
2021-02-12 23:24:14 +02:00
fillPrimarySkillData ( node , heroClass , PrimarySkill : : ATTACK ) ;
fillPrimarySkillData ( node , heroClass , PrimarySkill : : DEFENSE ) ;
fillPrimarySkillData ( node , heroClass , PrimarySkill : : SPELL_POWER ) ;
fillPrimarySkillData ( node , heroClass , PrimarySkill : : KNOWLEDGE ) ;
2013-04-21 15:49:26 +03:00
2021-07-28 17:54:32 +02:00
auto percentSumm = std : : accumulate ( heroClass - > primarySkillLowLevel . begin ( ) , heroClass - > primarySkillLowLevel . end ( ) , 0 ) ;
if ( percentSumm ! = 100 )
logMod - > error ( " Hero class %s has wrong lowLevelChance values: summ should be 100, but %d instead " , heroClass - > identifier , percentSumm ) ;
percentSumm = std : : accumulate ( heroClass - > primarySkillHighLevel . begin ( ) , heroClass - > primarySkillHighLevel . end ( ) , 0 ) ;
if ( percentSumm ! = 100 )
logMod - > error ( " Hero class %s has wrong highLevelChance values: summ should be 100, but %d instead " , heroClass - > identifier , percentSumm ) ;
2018-03-31 07:56:40 +02:00
for ( auto skillPair : node [ " secondarySkills " ] . Struct ( ) )
2013-04-21 15:49:26 +03:00
{
2020-10-01 10:38:06 +02:00
int probability = static_cast < int > ( skillPair . second . Integer ( ) ) ;
2018-03-31 07:56:40 +02:00
VLC - > modh - > identifiers . requestIdentifier ( skillPair . second . meta , " skill " , skillPair . first , [ heroClass , probability ] ( si32 skillID )
{
if ( heroClass - > secSkillProbability . size ( ) < = skillID )
heroClass - > secSkillProbability . resize ( skillID + 1 , - 1 ) ; // -1 = override with default later
heroClass - > secSkillProbability [ skillID ] = probability ;
} ) ;
2013-04-21 15:49:26 +03:00
}
2014-06-23 20:10:08 +03:00
VLC - > modh - > identifiers . requestIdentifier ( " creature " , node [ " commander " ] ,
[ = ] ( si32 commanderID )
2013-12-13 21:27: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
heroClass - > commander = VLC - > creh - > objects [ commanderID ] ;
2014-06-23 20:10:08 +03:00
} ) ;
2013-12-13 21:27:54 +03:00
2020-10-01 10:38:06 +02:00
heroClass - > defaultTavernChance = static_cast < ui32 > ( node [ " defaultTavern " ] . Float ( ) ) ;
2013-06-29 16:05:48 +03:00
for ( auto & tavern : node [ " tavern " ] . Struct ( ) )
2013-04-21 15:49:26 +03:00
{
2020-10-01 10:38:06 +02:00
int value = static_cast < int > ( tavern . second . Float ( ) ) ;
2013-04-21 15:49:26 +03:00
2013-04-25 17:03:35 +03:00
VLC - > modh - > identifiers . requestIdentifier ( tavern . second . meta , " faction " , tavern . first ,
2013-04-21 15:49:26 +03:00
[ = ] ( si32 factionID )
{
heroClass - > selectionProbability [ factionID ] = value ;
} ) ;
}
2013-04-25 17:03:35 +03:00
VLC - > modh - > identifiers . requestIdentifier ( " faction " , node [ " faction " ] ,
2013-04-21 15:49:26 +03:00
[ = ] ( si32 factionID )
{
heroClass - > faction = factionID ;
} ) ;
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 " , " hero " , [ = ] ( si32 index )
{
JsonNode classConf = node [ " mapObject " ] ;
classConf [ " heroClass " ] . String ( ) = identifier ;
classConf . setMeta ( scope ) ;
VLC - > objtypeh - > loadSubObject ( identifier , classConf , index , heroClass - > getIndex ( ) ) ;
} ) ;
2013-04-21 15:49:26 +03:00
return heroClass ;
}
std : : vector < JsonNode > CHeroClassHandler : : loadLegacyData ( size_t dataSize )
{
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 ) ;
2012-12-14 18:32:53 +03:00
CLegacyConfigParser parser ( " DATA/HCTRAITS.TXT " ) ;
parser . endLine ( ) ; // header
parser . endLine ( ) ;
2013-04-21 15:49:26 +03:00
for ( size_t i = 0 ; i < dataSize ; i + + )
2012-12-14 18:32:53 +03:00
{
2013-03-12 17:56:23 +03:00
JsonNode entry ;
entry [ " name " ] . String ( ) = parser . readString ( ) ;
parser . readNumber ( ) ; // unused aggression
2012-12-14 18:32:53 +03:00
2013-06-29 16:05:48 +03:00
for ( auto & name : PrimarySkill : : names )
entry [ " primarySkills " ] [ name ] . Float ( ) = parser . readNumber ( ) ;
2012-12-14 18:32:53 +03:00
2013-06-29 16:05:48 +03:00
for ( auto & name : PrimarySkill : : names )
entry [ " lowLevelChance " ] [ name ] . Float ( ) = parser . readNumber ( ) ;
2012-12-14 18:32:53 +03:00
2013-06-29 16:05:48 +03:00
for ( auto & name : PrimarySkill : : names )
entry [ " highLevelChance " ] [ name ] . Float ( ) = parser . readNumber ( ) ;
2009-01-11 00:08:18 +02:00
2013-06-29 16:05:48 +03:00
for ( auto & name : NSecondarySkill : : names )
entry [ " secondarySkills " ] [ name ] . Float ( ) = parser . readNumber ( ) ;
2012-12-14 18:32:53 +03:00
2013-06-29 16:05:48 +03:00
for ( auto & name : ETownType : : names )
entry [ " tavern " ] [ name ] . Float ( ) = parser . readNumber ( ) ;
2012-12-14 18:32:53 +03:00
2013-04-21 15:49:26 +03:00
parser . endLine ( ) ;
2013-03-12 17:56:23 +03:00
h3Data . push_back ( entry ) ;
2012-12-14 18:32:53 +03:00
}
2013-04-21 15:49:26 +03:00
return h3Data ;
2012-12-14 18:32:53 +03:00
}
2013-11-03 15:07:23 +03:00
void CHeroClassHandler : : afterLoadFinalization ( )
{
// for each pair <class, town> set selection probability if it was not set before in tavern entries
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 ( CHeroClass * heroClass : objects )
2013-11-03 15:07: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
for ( CFaction * faction : VLC - > townh - > objects )
2013-11-03 15:07:23 +03:00
{
if ( ! faction - > town )
continue ;
if ( heroClass - > selectionProbability . count ( faction - > index ) )
continue ;
2020-10-01 10:38:06 +02:00
float chance = static_cast < float > ( heroClass - > defaultTavernChance * faction - > town - > defaultTavernChance ) ;
2013-11-10 00:29:46 +03:00
heroClass - > selectionProbability [ faction - > index ] = static_cast < int > ( sqrt ( chance ) + 0.5 ) ; //FIXME: replace with std::round once MVS supports it
2013-11-03 15:07:23 +03:00
}
2018-03-31 07:56:40 +02:00
// set default probabilities for gaining secondary skills where not loaded previously
heroClass - > secSkillProbability . resize ( VLC - > skillh - > size ( ) , - 1 ) ;
for ( int skillID = 0 ; skillID < VLC - > skillh - > size ( ) ; skillID + + )
{
if ( heroClass - > secSkillProbability [ skillID ] < 0 )
{
const CSkill * skill = ( * VLC - > skillh ) [ SecondarySkill ( skillID ) ] ;
logMod - > trace ( " %s: no probability for %s, using default " , heroClass - > identifier , skill - > identifier ) ;
heroClass - > secSkillProbability [ skillID ] = skill - > gainChance [ heroClass - > affinity ] ;
}
}
2013-11-03 15:07:23 +03:00
}
2014-01-03 02:48:38 +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
for ( CHeroClass * hc : objects )
2014-01-03 02:48:38 +03:00
{
2014-06-04 11:25:13 +03:00
if ( ! hc - > imageMapMale . empty ( ) )
{
JsonNode templ ;
templ [ " animation " ] . String ( ) = hc - > imageMapMale ;
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 - > objtypeh - > getHandlerFor ( Obj : : HERO , hc - > getIndex ( ) ) - > addTemplate ( templ ) ;
2014-06-04 11:25:13 +03:00
}
2014-01-03 02:48:38 +03:00
}
2013-11-03 15:07:23 +03:00
}
2013-04-21 15:49:26 +03:00
std : : vector < bool > CHeroClassHandler : : getDefaultAllowed ( ) 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 std : : vector < bool > ( size ( ) , true ) ;
2012-12-14 18:32:53 +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
CHeroClassHandler : : ~ CHeroClassHandler ( ) = default ;
2012-12-14 18:32:53 +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
CHeroHandler : : ~ CHeroHandler ( ) = default ;
2009-01-11 00:08:18 +02:00
CHeroHandler : : CHeroHandler ( )
2012-12-26 12:46:09 +03:00
{
2013-04-21 15:49:26 +03:00
loadTerrains ( ) ;
2022-06-20 16:39:50 +02:00
for ( int i = 0 ; i < Terrain : : Manager : : terrains ( ) . size ( ) ; + + i )
2016-02-04 18:57:51 +02:00
{
2022-06-20 16:39:50 +02:00
VLC - > modh - > identifiers . registerObject ( " core " , " terrain " , Terrain : : Manager : : terrains ( ) [ i ] , i ) ;
2016-02-04 18:57:51 +02:00
}
2013-04-21 15:49:26 +03:00
loadBallistics ( ) ;
loadExperience ( ) ;
2012-12-15 11:47:02 +03:00
}
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const std : : vector < std : : string > & CHeroHandler : : getTypeNames ( ) const
{
static const std : : vector < std : : string > typeNames = { " hero " } ;
return typeNames ;
}
CHero * CHeroHandler : : loadFromJson ( const std : : string & scope , const JsonNode & node , const std : : string & identifier , size_t index )
2012-12-15 11:47:02 +03:00
{
2017-07-16 11:58:05 +02:00
auto hero = new CHero ( ) ;
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
hero - > ID = HeroTypeID ( index ) ;
2015-08-24 10:55:45 +02:00
hero - > identifier = identifier ;
2013-03-03 21:00:37 +03:00
hero - > sex = node [ " female " ] . Bool ( ) ;
hero - > special = node [ " special " ] . Bool ( ) ;
2012-12-16 16:47:53 +03:00
hero - > name = node [ " texts " ] [ " name " ] . String ( ) ;
hero - > biography = node [ " texts " ] [ " biography " ] . String ( ) ;
hero - > specName = node [ " texts " ] [ " specialty " ] [ " name " ] . String ( ) ;
hero - > specTooltip = node [ " texts " ] [ " specialty " ] [ " tooltip " ] . String ( ) ;
hero - > specDescr = node [ " texts " ] [ " specialty " ] [ " description " ] . String ( ) ;
hero - > iconSpecSmall = node [ " images " ] [ " specialtySmall " ] . String ( ) ;
hero - > iconSpecLarge = node [ " images " ] [ " specialtyLarge " ] . String ( ) ;
hero - > portraitSmall = node [ " images " ] [ " small " ] . String ( ) ;
hero - > portraitLarge = node [ " images " ] [ " large " ] . String ( ) ;
2018-09-13 01:33:34 +02:00
hero - > battleImage = node [ " battleImage " ] . String ( ) ;
2012-12-16 16:47:53 +03:00
2013-03-03 21:00:37 +03:00
loadHeroArmy ( hero , node ) ;
loadHeroSkills ( hero , node ) ;
loadHeroSpecialty ( hero , node ) ;
2013-04-25 17:03:35 +03:00
VLC - > modh - > identifiers . requestIdentifier ( " heroClass " , node [ " class " ] ,
2013-03-03 21:00:37 +03:00
[ = ] ( si32 classID )
{
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
hero - > heroClass = classes [ HeroClassID ( classID ) ] ;
2013-03-03 21:00:37 +03:00
} ) ;
return hero ;
}
void CHeroHandler : : loadHeroArmy ( CHero * hero , const JsonNode & node )
{
2012-12-16 16:47:53 +03:00
assert ( node [ " army " ] . Vector ( ) . size ( ) < = 3 ) ; // anything bigger is useless - army initialization uses up to 3 slots
2013-03-03 21:00:37 +03:00
2012-12-16 16:47:53 +03:00
hero - > initialArmy . resize ( node [ " army " ] . Vector ( ) . size ( ) ) ;
for ( size_t i = 0 ; i < hero - > initialArmy . size ( ) ; i + + )
{
const JsonNode & source = node [ " army " ] . Vector ( ) [ i ] ;
2020-10-01 10:38:06 +02:00
hero - > initialArmy [ i ] . minAmount = static_cast < ui32 > ( source [ " min " ] . Float ( ) ) ;
hero - > initialArmy [ i ] . maxAmount = static_cast < ui32 > ( source [ " max " ] . Float ( ) ) ;
2012-12-16 16:47:53 +03:00
assert ( hero - > initialArmy [ i ] . minAmount < = hero - > initialArmy [ i ] . maxAmount ) ;
2013-04-25 17:03:35 +03:00
VLC - > modh - > identifiers . requestIdentifier ( " creature " , source [ " creature " ] , [ = ] ( si32 creature )
2012-12-16 16:47:53 +03:00
{
2013-02-11 02:24:57 +03:00
hero - > initialArmy [ i ] . creature = CreatureID ( creature ) ;
2012-12-16 16:47:53 +03:00
} ) ;
}
}
2013-03-03 21:00:37 +03:00
void CHeroHandler : : loadHeroSkills ( CHero * hero , const JsonNode & node )
2012-12-16 16:47:53 +03:00
{
2013-06-29 16:05:48 +03:00
for ( const JsonNode & set : node [ " skills " ] . Vector ( ) )
2012-12-16 16:47:53 +03:00
{
2020-10-01 10:38:06 +02:00
int skillLevel = static_cast < int > ( boost : : range : : find ( NSecondarySkill : : levels , set [ " level " ] . String ( ) ) - std : : begin ( NSecondarySkill : : levels ) ) ;
2013-04-23 12:16:20 +03:00
if ( skillLevel < SecSkillLevel : : LEVELS_SIZE )
{
size_t currentIndex = hero - > secSkillsInit . size ( ) ;
2013-04-25 11:22:04 +03:00
hero - > secSkillsInit . push_back ( std : : make_pair ( SecondarySkill ( - 1 ) , skillLevel ) ) ;
2013-04-23 12:16:20 +03:00
2013-04-25 17:03:35 +03:00
VLC - > modh - > identifiers . requestIdentifier ( " skill " , set [ " skill " ] , [ = ] ( si32 id )
2013-04-23 12:16:20 +03:00
{
hero - > secSkillsInit [ currentIndex ] . first = SecondarySkill ( id ) ;
} ) ;
}
else
{
2017-08-30 23:23:19 +02:00
logMod - > error ( " Unknown skill level: %s " , set [ " level " ] . String ( ) ) ;
2013-04-23 12:16:20 +03:00
}
2012-12-16 16:47:53 +03:00
}
2013-03-02 19:55:51 +03:00
// spellbook is considered present if hero have "spellbook" entry even when this is an empty set (0 spells)
2013-03-03 21:00:37 +03:00
hero - > haveSpellBook = ! node [ " spellbook " ] . isNull ( ) ;
2013-03-02 19:55:51 +03:00
2013-06-29 16:05:48 +03:00
for ( const JsonNode & spell : node [ " spellbook " ] . Vector ( ) )
2012-12-16 16:47:53 +03:00
{
2013-08-19 14:50:53 +03:00
VLC - > modh - > identifiers . requestIdentifier ( " spell " , spell ,
[ = ] ( si32 spellID )
2013-03-02 19:55:51 +03:00
{
2013-08-19 14:50:53 +03:00
hero - > spells . insert ( SpellID ( spellID ) ) ;
} ) ;
2012-12-16 16:47:53 +03:00
}
2013-03-03 21:00:37 +03:00
}
2012-12-16 16:47:53 +03:00
2018-02-06 02:44:43 +02:00
// add standard creature specialty to result
void AddSpecialtyForCreature ( int creatureID , std : : shared_ptr < Bonus > bonus , std : : vector < std : : shared_ptr < Bonus > > & result )
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const CCreature & specBaseCreature = * VLC - > creh - > objects [ creatureID ] ; //base creature in which we have specialty
2018-02-06 02:44:43 +02:00
bonus - > limiter . reset ( new CCreatureTypeLimiter ( specBaseCreature , true ) ) ;
bonus - > type = Bonus : : STACKS_SPEED ;
bonus - > valType = Bonus : : ADDITIVE_VALUE ;
bonus - > val = 1 ;
result . push_back ( bonus ) ;
// attack and defense may differ for upgraded creatures => separate bonuses
std : : vector < int > specTargets ;
specTargets . push_back ( creatureID ) ;
specTargets . insert ( specTargets . end ( ) , specBaseCreature . upgrades . begin ( ) , specBaseCreature . upgrades . end ( ) ) ;
for ( int cid : specTargets )
{
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
const CCreature & specCreature = * VLC - > creh - > objects [ cid ] ;
2018-02-06 02:44:43 +02:00
bonus = std : : make_shared < Bonus > ( * bonus ) ;
bonus - > limiter . reset ( new CCreatureTypeLimiter ( specCreature , false ) ) ;
bonus - > type = Bonus : : PRIMARY_SKILL ;
bonus - > val = 0 ;
int stepSize = specCreature . level ? specCreature . level : 5 ;
bonus - > subtype = PrimarySkill : : ATTACK ;
bonus - > updater . reset ( new GrowsWithLevelUpdater ( specCreature . getAttack ( false ) , stepSize ) ) ;
result . push_back ( bonus ) ;
bonus = std : : make_shared < Bonus > ( * bonus ) ;
bonus - > subtype = PrimarySkill : : DEFENSE ;
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
bonus - > updater . reset ( new GrowsWithLevelUpdater ( specCreature . getDefense ( false ) , stepSize ) ) ;
2018-02-06 02:44:43 +02:00
result . push_back ( bonus ) ;
}
}
2017-09-10 04:10:50 +02:00
// convert deprecated format
std : : vector < std : : shared_ptr < Bonus > > SpecialtyInfoToBonuses ( const SSpecialtyInfo & spec , int sid )
{
std : : vector < std : : shared_ptr < Bonus > > result ;
std : : shared_ptr < Bonus > bonus = std : : make_shared < Bonus > ( ) ;
bonus - > duration = Bonus : : PERMANENT ;
bonus - > source = Bonus : : HERO_SPECIAL ;
bonus - > sid = sid ;
bonus - > val = spec . val ;
switch ( spec . type )
{
2017-09-15 13:32:32 +02:00
case 1 : //creature specialty
2018-02-06 02:44:43 +02:00
AddSpecialtyForCreature ( spec . additionalinfo , bonus , result ) ;
2017-09-15 13:32:32 +02:00
break ;
case 2 : //secondary skill
bonus - > type = Bonus : : SECONDARY_SKILL_PREMY ;
bonus - > valType = Bonus : : PERCENT_TO_BASE ;
bonus - > subtype = spec . subtype ;
2017-09-19 00:08:28 +02:00
bonus - > updater . reset ( new TimesHeroLevelUpdater ( ) ) ;
2017-09-15 13:32:32 +02:00
result . push_back ( bonus ) ;
break ;
case 3 : //spell damage bonus, level dependent but calculated elsewhere
bonus - > type = Bonus : : SPECIAL_SPELL_LEV ;
bonus - > subtype = spec . subtype ;
2018-02-20 22:56:20 +02:00
bonus - > updater . reset ( new TimesHeroLevelUpdater ( ) ) ;
2017-09-15 13:32:32 +02:00
result . push_back ( bonus ) ;
break ;
case 4 : //creature stat boost
switch ( spec . subtype )
{
case 1 :
bonus - > type = Bonus : : PRIMARY_SKILL ;
bonus - > subtype = PrimarySkill : : ATTACK ;
2017-09-10 04:10:50 +02:00
break ;
2017-09-15 13:32:32 +02:00
case 2 :
bonus - > type = Bonus : : PRIMARY_SKILL ;
bonus - > subtype = PrimarySkill : : DEFENSE ;
2017-09-10 04:10:50 +02:00
break ;
2017-09-15 13:32:32 +02:00
case 3 :
bonus - > type = Bonus : : CREATURE_DAMAGE ;
bonus - > subtype = 0 ; //both min and max
2017-09-10 04:10:50 +02:00
break ;
2017-09-15 13:32:32 +02:00
case 4 :
bonus - > type = Bonus : : STACK_HEALTH ;
2017-09-10 04:10:50 +02:00
break ;
2017-09-15 13:32:32 +02:00
case 5 :
bonus - > type = Bonus : : STACKS_SPEED ;
2017-09-10 04:10:50 +02:00
break ;
2017-09-15 13:32:32 +02:00
default :
logMod - > warn ( " Unknown subtype for specialty 4 " ) ;
return result ;
}
bonus - > valType = Bonus : : ADDITIVE_VALUE ;
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
bonus - > limiter . reset ( new CCreatureTypeLimiter ( * VLC - > creh - > objects [ spec . additionalinfo ] , true ) ) ;
2017-09-15 13:32:32 +02:00
result . push_back ( bonus ) ;
break ;
case 5 : //spell damage bonus in percent
bonus - > type = Bonus : : SPECIFIC_SPELL_DAMAGE ;
bonus - > valType = Bonus : : BASE_NUMBER ; //current spell system is screwed
bonus - > subtype = spec . subtype ; //spell id
result . push_back ( bonus ) ;
break ;
case 6 : //damage bonus for bless (Adela)
bonus - > type = Bonus : : SPECIAL_BLESS_DAMAGE ;
bonus - > subtype = spec . subtype ; //spell id if you ever wanted to use it otherwise
bonus - > additionalInfo = spec . additionalinfo ; //damage factor
2018-02-20 22:56:20 +02:00
bonus - > updater . reset ( new TimesHeroLevelUpdater ( ) ) ;
2017-09-15 13:32:32 +02:00
result . push_back ( bonus ) ;
break ;
case 7 : //maxed mastery for spell
bonus - > type = Bonus : : MAXED_SPELL ;
bonus - > subtype = spec . subtype ; //spell id
result . push_back ( bonus ) ;
break ;
case 8 : //peculiar spells - enchantments
bonus - > type = Bonus : : SPECIAL_PECULIAR_ENCHANT ;
bonus - > subtype = spec . subtype ; //spell id
bonus - > additionalInfo = spec . additionalinfo ; //0, 1 for Coronius
result . push_back ( bonus ) ;
break ;
case 9 : //upgrade creatures
{
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 auto & creatures = VLC - > creh - > objects ;
2017-09-15 13:32:32 +02:00
bonus - > type = Bonus : : SPECIAL_UPGRADE ;
bonus - > subtype = spec . subtype ; //base id
bonus - > additionalInfo = spec . additionalinfo ; //target id
2017-09-10 04:10:50 +02:00
result . push_back ( bonus ) ;
2017-09-15 13:32:32 +02:00
//propagate for regular upgrades of base creature
for ( auto cre_id : creatures [ spec . subtype ] - > upgrades )
2017-09-10 04:10:50 +02:00
{
2017-09-17 05:48:01 +02:00
std : : shared_ptr < Bonus > upgradeUpgradedVersion = std : : make_shared < Bonus > ( * bonus ) ;
upgradeUpgradedVersion - > subtype = cre_id ;
result . push_back ( upgradeUpgradedVersion ) ;
2017-09-10 04:10:50 +02:00
}
2017-09-15 13:32:32 +02:00
}
break ;
case 10 : //resource generation
bonus - > type = Bonus : : GENERATE_RESOURCE ;
bonus - > subtype = spec . subtype ;
result . push_back ( bonus ) ;
break ;
case 11 : //starting skill with mastery (Adrienne)
logMod - > warn ( " Secondary skill mastery is no longer supported as specialty. " ) ;
break ;
case 12 : //army speed
bonus - > type = Bonus : : STACKS_SPEED ;
result . push_back ( bonus ) ;
break ;
case 13 : //Dragon bonuses (Mutare)
bonus - > type = Bonus : : PRIMARY_SKILL ;
bonus - > valType = Bonus : : ADDITIVE_VALUE ;
switch ( spec . subtype )
{
case 1 :
bonus - > subtype = PrimarySkill : : ATTACK ;
2017-09-10 04:10:50 +02:00
break ;
2017-09-15 13:32:32 +02:00
case 2 :
bonus - > subtype = PrimarySkill : : DEFENSE ;
2017-09-10 04:10:50 +02:00
break ;
2017-09-15 13:32:32 +02:00
}
bonus - > limiter . reset ( new HasAnotherBonusLimiter ( Bonus : : DRAGON_NATURE ) ) ;
result . push_back ( bonus ) ;
break ;
default :
logMod - > warn ( " Unknown hero specialty %d " , spec . type ) ;
break ;
2017-09-10 04:10:50 +02:00
}
return result ;
}
2017-09-14 23:25:43 +02:00
// convert deprecated format
2018-10-29 22:33:13 +02:00
std : : vector < std : : shared_ptr < Bonus > > SpecialtyBonusToBonuses ( const SSpecialtyBonus & spec , int sid )
2017-09-14 23:25:43 +02:00
{
std : : vector < std : : shared_ptr < Bonus > > result ;
for ( std : : shared_ptr < Bonus > oldBonus : spec . bonuses )
{
2018-10-29 22:33:13 +02:00
oldBonus - > sid = sid ;
2018-02-20 22:56:20 +02:00
if ( oldBonus - > type = = Bonus : : SPECIAL_SPELL_LEV | | oldBonus - > type = = Bonus : : SPECIAL_BLESS_DAMAGE )
{
// these bonuses used to auto-scale with hero level
std : : shared_ptr < Bonus > newBonus = std : : make_shared < Bonus > ( * oldBonus ) ;
newBonus - > updater = std : : make_shared < TimesHeroLevelUpdater > ( ) ;
result . push_back ( newBonus ) ;
}
else if ( spec . growsWithLevel )
2017-09-14 23:25:43 +02:00
{
std : : shared_ptr < Bonus > newBonus = std : : make_shared < Bonus > ( * oldBonus ) ;
switch ( newBonus - > type )
{
case Bonus : : SECONDARY_SKILL_PREMY :
break ; // ignore - used to be overwritten based on SPECIAL_SECONDARY_SKILL
case Bonus : : SPECIAL_SECONDARY_SKILL :
newBonus - > type = Bonus : : SECONDARY_SKILL_PREMY ;
2017-09-19 00:08:28 +02:00
newBonus - > updater = std : : make_shared < TimesHeroLevelUpdater > ( ) ;
2017-09-14 23:25:43 +02:00
result . push_back ( newBonus ) ;
break ;
case Bonus : : PRIMARY_SKILL :
if ( ( newBonus - > subtype = = PrimarySkill : : ATTACK | | newBonus - > subtype = = PrimarySkill : : DEFENSE ) & & newBonus - > limiter )
{
2020-10-01 07:55:41 +02:00
std : : shared_ptr < CCreatureTypeLimiter > creatureLimiter = std : : dynamic_pointer_cast < CCreatureTypeLimiter > ( newBonus - > limiter ) ;
2017-09-14 23:25:43 +02:00
if ( creatureLimiter )
{
const CCreature * cre = creatureLimiter - > creature ;
Entities redesign and a few ERM features
* Made most Handlers derived from CHandlerBase and moved service API there.
* Declared existing Entity APIs.
* Added basic script context caching
* Started Lua script module
* Started Lua spell effect API
* Started script state persistence
* Started battle info callback binding
* CommitPackage removed
* Extracted spells::Caster to own header; Expanded Spell API.
* implemented !!MC:S, !!FU:E, !!FU:P, !!MA, !!VR:H, !!VR:C
* !!BU:C, !!BU:E, !!BU:G, !!BU:M implemented
* Allow use of "MC:S@varName@" to declare normal variable (technically v-variable with string key)
* Re-enabled VERM macros.
* !?GM0 added
* !?TM implemented
* Added !!MF:N
* Started !?OB, !!BM, !!HE, !!OW, !!UN
* Added basic support of w-variables
* Added support for ERM indirect variables
* Made !?FU regular trigger
* !!re (ERA loop receiver) implemented
* Fixed ERM receivers with zero args.
2018-03-17 16:58:30 +02:00
int creStat = newBonus - > subtype = = PrimarySkill : : ATTACK ? cre - > getAttack ( false ) : cre - > getDefense ( false ) ;
2017-09-14 23:25:43 +02:00
int creLevel = cre - > level ? cre - > level : 5 ;
2017-09-19 00:08:28 +02:00
newBonus - > updater = std : : make_shared < GrowsWithLevelUpdater > ( creStat , creLevel ) ;
2017-09-14 23:25:43 +02:00
}
result . push_back ( newBonus ) ;
}
break ;
default :
result . push_back ( newBonus ) ;
}
}
else
{
result . push_back ( oldBonus ) ;
}
}
return result ;
}
2017-09-14 00:45:54 +02:00
void CHeroHandler : : beforeValidate ( JsonNode & object )
{
//handle "base" specialty info
2017-09-14 09:03:25 +02:00
JsonNode & specialtyNode = object [ " specialty " ] ;
2017-09-14 03:03:44 +02:00
if ( specialtyNode . getType ( ) = = JsonNode : : JsonType : : DATA_STRUCT )
2017-09-14 00:45:54 +02:00
{
const JsonNode & base = specialtyNode [ " base " ] ;
if ( ! base . isNull ( ) )
{
2018-02-06 02:44:43 +02:00
if ( specialtyNode [ " bonuses " ] . isNull ( ) )
{
logMod - > warn ( " specialty has base without bonuses " ) ;
}
else
{
JsonMap & bonuses = specialtyNode [ " bonuses " ] . Struct ( ) ;
for ( std : : pair < std : : string , JsonNode > keyValue : bonuses )
JsonUtils : : inherit ( bonuses [ keyValue . first ] , base ) ;
}
2017-09-14 00:45:54 +02:00
}
}
}
2013-03-03 21:00:37 +03:00
void CHeroHandler : : loadHeroSpecialty ( CHero * hero , const JsonNode & node )
{
2017-09-10 04:10:50 +02:00
int sid = hero - > ID . getNum ( ) ;
auto prepSpec = [ = ] ( std : : shared_ptr < Bonus > bonus )
{
bonus - > duration = Bonus : : PERMANENT ;
bonus - > source = Bonus : : HERO_SPECIAL ;
bonus - > sid = sid ;
return bonus ;
} ;
2017-09-11 08:21:24 +02:00
//deprecated, used only for original specialties
2017-09-14 00:45:54 +02:00
const JsonNode & specialtiesNode = node [ " specialties " ] ;
if ( ! specialtiesNode . isNull ( ) )
2012-12-16 16:47:53 +03:00
{
2017-09-12 14:59:50 +02:00
logMod - > warn ( " Hero %s has deprecated specialties format. " , hero - > identifier ) ;
2017-09-14 00:45:54 +02:00
for ( const JsonNode & specialty : specialtiesNode . Vector ( ) )
2017-09-11 08:21:24 +02:00
{
SSpecialtyInfo spec ;
2020-10-01 10:38:06 +02:00
spec . type = static_cast < si32 > ( specialty [ " type " ] . Integer ( ) ) ;
spec . val = static_cast < si32 > ( specialty [ " val " ] . Integer ( ) ) ;
spec . subtype = static_cast < si32 > ( specialty [ " subtype " ] . Integer ( ) ) ;
spec . additionalinfo = static_cast < si32 > ( specialty [ " info " ] . Integer ( ) ) ;
2017-09-12 14:59:50 +02:00
//we convert after loading completes, to have all identifiers for json logging
hero - > specDeprecated . push_back ( spec ) ;
2017-09-11 08:21:24 +02:00
}
2012-12-16 16:47:53 +03:00
}
2017-09-14 00:45:54 +02:00
//new(er) format, using bonus system
const JsonNode & specialtyNode = node [ " specialty " ] ;
2017-09-14 03:03:44 +02:00
if ( specialtyNode . getType ( ) = = JsonNode : : JsonType : : DATA_VECTOR )
2013-01-19 20:38:37 +03:00
{
2017-09-14 00:45:54 +02:00
//deprecated middle-aged format
for ( const JsonNode & specialty : node [ " specialty " ] . Vector ( ) )
2017-09-10 04:10:50 +02:00
{
2017-09-14 23:25:43 +02:00
SSpecialtyBonus hs ;
hs . growsWithLevel = specialty [ " growsWithLevel " ] . Bool ( ) ;
2017-09-10 04:10:50 +02:00
for ( const JsonNode & bonus : specialty [ " bonuses " ] . Vector ( ) )
2017-09-14 23:25:43 +02:00
hs . bonuses . push_back ( prepSpec ( JsonUtils : : parseBonus ( bonus ) ) ) ;
hero - > specialtyDeprecated . push_back ( hs ) ;
2017-09-10 04:10:50 +02:00
}
2017-09-14 00:45:54 +02:00
}
2017-09-14 03:03:44 +02:00
else if ( specialtyNode . getType ( ) = = JsonNode : : JsonType : : DATA_STRUCT )
2017-09-14 00:45:54 +02:00
{
2018-02-06 02:44:43 +02:00
//creature specialty - alias for simplicity
if ( ! specialtyNode [ " creature " ] . isNull ( ) )
{
VLC - > modh - > identifiers . requestIdentifier ( " creature " , specialtyNode [ " creature " ] , [ hero ] ( si32 creature ) {
// use legacy format for delayed conversion (must have all creature data loaded, also for upgrades)
SSpecialtyInfo spec ;
spec . type = 1 ;
spec . additionalinfo = creature ;
hero - > specDeprecated . push_back ( spec ) ;
} ) ;
}
if ( ! specialtyNode [ " bonuses " ] . isNull ( ) )
{
//proper new format
for ( auto keyValue : specialtyNode [ " bonuses " ] . Struct ( ) )
hero - > specialty . push_back ( prepSpec ( JsonUtils : : parseBonus ( keyValue . second ) ) ) ;
}
2013-01-19 20:38:37 +03:00
}
2012-12-15 11:47:02 +03:00
}
void CHeroHandler : : loadExperience ( )
{
expPerLevel . push_back ( 0 ) ;
expPerLevel . push_back ( 1000 ) ;
expPerLevel . push_back ( 2000 ) ;
expPerLevel . push_back ( 3200 ) ;
expPerLevel . push_back ( 4600 ) ;
expPerLevel . push_back ( 6200 ) ;
expPerLevel . push_back ( 8000 ) ;
expPerLevel . push_back ( 10000 ) ;
expPerLevel . push_back ( 12200 ) ;
expPerLevel . push_back ( 14700 ) ;
expPerLevel . push_back ( 17500 ) ;
expPerLevel . push_back ( 20600 ) ;
expPerLevel . push_back ( 24320 ) ;
expPerLevel . push_back ( 28784 ) ;
expPerLevel . push_back ( 34140 ) ;
while ( expPerLevel [ expPerLevel . size ( ) - 1 ] > expPerLevel [ expPerLevel . size ( ) - 2 ] )
{
2018-04-28 19:51:30 +02:00
auto i = expPerLevel . size ( ) - 1 ;
auto diff = expPerLevel [ i ] - expPerLevel [ i - 1 ] ;
diff + = diff / 5 ;
expPerLevel . push_back ( expPerLevel [ i ] + diff ) ;
2012-12-15 11:47:02 +03:00
}
expPerLevel . pop_back ( ) ; //last value is broken
2012-12-14 18:32:53 +03:00
}
2013-03-03 21:00:37 +03:00
/// convert h3-style ID (e.g. Gobin Wolf Rider) to vcmi (e.g. goblinWolfRider)
static std : : string genRefName ( std : : string input )
{
boost : : algorithm : : replace_all ( input , " " , " " ) ; //remove spaces
input [ 0 ] = std : : tolower ( input [ 0 ] ) ; // to camelCase
return input ;
}
2013-04-21 15:49:26 +03:00
void CHeroHandler : : loadBallistics ( )
{
CLegacyConfigParser ballParser ( " DATA/BALLIST.TXT " ) ;
ballParser . endLine ( ) ; //header
ballParser . endLine ( ) ;
do
{
ballParser . readString ( ) ;
ballParser . readString ( ) ;
CHeroHandler : : SBallisticsLevelInfo bli ;
2020-10-01 10:38:06 +02:00
bli . keep = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . tower = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . gate = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . wall = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . shots = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . noDmg = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . oneDmg = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . twoDmg = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
bli . sum = static_cast < ui8 > ( ballParser . readNumber ( ) ) ;
2013-04-21 15:49:26 +03:00
ballistics . push_back ( bli ) ;
2013-08-06 14:20:28 +03:00
assert ( bli . noDmg + bli . oneDmg + bli . twoDmg = = 100 & & bli . sum = = 100 ) ;
2013-04-21 15:49:26 +03:00
}
while ( ballParser . endLine ( ) ) ;
}
std : : vector < JsonNode > CHeroHandler : : loadLegacyData ( size_t dataSize )
2007-06-08 17:58:04 +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
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
CLegacyConfigParser specParser ( " DATA/HEROSPEC.TXT " ) ;
CLegacyConfigParser bioParser ( " DATA/HEROBIOS.TXT " ) ;
2012-08-25 11:44:51 +03:00
CLegacyConfigParser parser ( " DATA/HOTRAITS.TXT " ) ;
parser . endLine ( ) ; //ignore header
parser . endLine ( ) ;
2007-08-04 22:01:22 +03:00
2013-03-02 19:55:51 +03:00
specParser . endLine ( ) ; //ignore header
specParser . endLine ( ) ;
2011-12-14 00:23:17 +03:00
for ( int i = 0 ; i < GameConstants : : HEROES_QUANTITY ; i + + )
2007-06-08 17:58:04 +03:00
{
2013-03-03 21:00:37 +03:00
JsonNode heroData ;
heroData [ " texts " ] [ " name " ] . String ( ) = parser . readString ( ) ;
heroData [ " texts " ] [ " biography " ] . String ( ) = bioParser . readString ( ) ;
heroData [ " texts " ] [ " specialty " ] [ " name " ] . String ( ) = specParser . readString ( ) ;
heroData [ " texts " ] [ " specialty " ] [ " tooltip " ] . String ( ) = specParser . readString ( ) ;
heroData [ " texts " ] [ " specialty " ] [ " description " ] . String ( ) = specParser . readString ( ) ;
2007-08-04 22:01:22 +03:00
2008-05-03 18:30:11 +03:00
for ( int x = 0 ; x < 3 ; x + + )
{
2013-03-03 21:00:37 +03:00
JsonNode armySlot ;
armySlot [ " min " ] . Float ( ) = parser . readNumber ( ) ;
armySlot [ " max " ] . Float ( ) = parser . readNumber ( ) ;
armySlot [ " creature " ] . String ( ) = genRefName ( parser . readString ( ) ) ;
2012-12-03 19:00:17 +03:00
2013-03-03 21:00:37 +03:00
heroData [ " army " ] . Vector ( ) . push_back ( armySlot ) ;
2008-05-03 18:30:11 +03:00
}
2012-08-25 11:44:51 +03:00
parser . endLine ( ) ;
2013-03-02 19:55:51 +03:00
specParser . endLine ( ) ;
bioParser . endLine ( ) ;
2012-08-25 11:44:51 +03:00
2013-03-03 21:00:37 +03:00
h3Data . push_back ( heroData ) ;
2007-06-08 17:58:04 +03:00
}
2013-04-21 15:49:26 +03:00
return h3Data ;
}
2011-08-27 18:53:45 +03:00
2013-04-21 15:49:26 +03:00
void CHeroHandler : : loadObject ( std : : string scope , std : : string name , const JsonNode & data )
{
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
size_t index = objects . size ( ) ;
auto object = loadFromJson ( scope , data , normalizeIdentifier ( scope , " core " , name ) , index ) ;
object - > imageIndex = ( si32 ) index + GameConstants : : HERO_PORTRAIT_SHIFT ; // 2 special frames + some extra portraits
2013-03-03 21:00: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
objects . push_back ( object ) ;
2013-03-03 21:00: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
registerObject ( scope , " hero " , name , object - > getIndex ( ) ) ;
2012-12-16 16:47:53 +03:00
}
2011-08-27 20:33:07 +03:00
2013-04-21 15:49:26 +03:00
void CHeroHandler : : loadObject ( std : : string scope , std : : string name , const JsonNode & data , size_t index )
2012-12-15 11:47: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
auto object = loadFromJson ( scope , data , normalizeIdentifier ( scope , " core " , name ) , index ) ;
2020-10-01 10:38:06 +02:00
object - > imageIndex = static_cast < si32 > ( index ) ;
2012-08-25 11:44: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
assert ( objects [ index ] = = nullptr ) ; // ensure that this id was not loaded before
objects [ index ] = object ;
2012-08-25 11:44: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
registerObject ( scope , " hero " , name , object - > getIndex ( ) ) ;
2007-06-09 16:28:03 +03:00
}
2011-08-27 20:33:07 +03:00
2017-09-12 14:59:50 +02:00
void CHeroHandler : : afterLoadFinalization ( )
{
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 & hero : objects )
2017-09-12 14:59:50 +02:00
{
2018-10-29 22:33:13 +02:00
for ( auto bonus : hero - > specialty )
{
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
bonus - > sid = hero - > getIndex ( ) ;
2018-10-29 22:33:13 +02:00
}
2017-09-14 23:25:43 +02:00
if ( hero - > specDeprecated . size ( ) > 0 | | hero - > specialtyDeprecated . size ( ) > 0 )
2017-09-12 14:59:50 +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
logMod - > debug ( " Converting specialty format for hero %s(%s) " , hero - > identifier , FactionID : : encode ( hero - > heroClass - > faction ) ) ;
2017-09-14 23:25:43 +02:00
std : : vector < std : : shared_ptr < Bonus > > convertedBonuses ;
for ( const SSpecialtyInfo & spec : hero - > specDeprecated )
{
for ( std : : shared_ptr < Bonus > b : SpecialtyInfoToBonuses ( spec , hero - > ID . getNum ( ) ) )
convertedBonuses . push_back ( b ) ;
}
for ( const SSpecialtyBonus & spec : hero - > specialtyDeprecated )
{
2018-10-29 22:33:13 +02:00
for ( std : : shared_ptr < Bonus > b : SpecialtyBonusToBonuses ( spec , hero - > ID . getNum ( ) ) )
2017-09-14 23:25:43 +02:00
convertedBonuses . push_back ( b ) ;
}
2017-09-15 13:49:43 +02:00
hero - > specDeprecated . clear ( ) ;
hero - > specialtyDeprecated . clear ( ) ;
2017-09-14 23:25:43 +02:00
// store and create json for logging
2017-09-13 08:58:14 +02:00
std : : vector < JsonNode > specVec ;
std : : vector < std : : string > specNames ;
2017-09-14 23:25:43 +02:00
for ( std : : shared_ptr < Bonus > bonus : convertedBonuses )
2017-09-12 14:59:50 +02:00
{
2017-09-14 23:25:43 +02:00
hero - > specialty . push_back ( bonus ) ;
specVec . push_back ( bonus - > toJsonNode ( ) ) ;
// find fitting & unique bonus name
2017-09-15 00:48:34 +02:00
std : : string bonusName = bonus - > nameForBonus ( ) ;
2017-09-14 23:25:43 +02:00
if ( vstd : : contains ( specNames , bonusName ) )
2017-09-12 14:59:50 +02:00
{
2017-09-14 23:25:43 +02:00
int suffix = 2 ;
while ( vstd : : contains ( specNames , bonusName + std : : to_string ( suffix ) ) )
suffix + + ;
bonusName + = std : : to_string ( suffix ) ;
2017-09-12 14:59:50 +02:00
}
2017-09-14 23:25:43 +02:00
specNames . push_back ( bonusName ) ;
2017-09-12 14:59:50 +02:00
}
2017-09-13 08:58:14 +02:00
// log new format for easy copy-and-paste
JsonNode specNode ( JsonNode : : JsonType : : DATA_STRUCT ) ;
if ( specVec . size ( ) > 1 )
{
JsonNode base = JsonUtils : : intersect ( specVec ) ;
2017-09-16 00:23:31 +02:00
if ( base . containsBaseData ( ) )
2017-09-13 08:58:14 +02:00
{
specNode [ " base " ] = base ;
2017-09-13 10:27:01 +02:00
for ( JsonNode & node : specVec )
node = JsonUtils : : difference ( node , base ) ;
2017-09-13 08:58:14 +02:00
}
}
// add json for bonuses
specNode [ " bonuses " ] . Struct ( ) ;
for ( int i = 0 ; i < specVec . size ( ) ; i + + )
specNode [ " bonuses " ] [ specNames [ i ] ] = specVec [ i ] ;
2017-09-14 03:03:44 +02:00
logMod - > trace ( " \" specialty \" : %s " , specNode . toJson ( true ) ) ;
2017-09-12 14:59:50 +02:00
}
}
}
2011-12-14 00:23:17 +03:00
ui32 CHeroHandler : : level ( ui64 experience ) const
2007-08-12 20:48:05 +03:00
{
2020-10-01 10:38:06 +02:00
return static_cast < ui32 > ( boost : : range : : upper_bound ( expPerLevel , experience ) - std : : begin ( expPerLevel ) ) ;
2008-01-27 18:07:27 +02:00
}
2011-12-14 00:23:17 +03:00
ui64 CHeroHandler : : reqExp ( ui32 level ) const
2008-01-27 18:07:27 +02:00
{
2009-07-20 06:30:48 +03:00
if ( ! level )
return 0 ;
2009-10-28 12:45:45 +02:00
if ( level < = expPerLevel . size ( ) )
2009-07-20 06:30:48 +03:00
{
2009-10-28 12:45:45 +02:00
return expPerLevel [ level - 1 ] ;
2009-07-20 06:30:48 +03:00
}
2008-01-27 18:07:27 +02:00
else
2007-09-14 16:11:10 +03:00
{
2016-08-12 11:10:27 +02:00
logGlobal - > warn ( " A hero has reached unsupported amount of experience " ) ;
2010-08-16 12:54:09 +03:00
return expPerLevel [ expPerLevel . size ( ) - 1 ] ;
2007-09-14 16:11:10 +03:00
}
2007-08-12 20:48:05 +03:00
}
2011-09-02 06:39:49 +03:00
void CHeroHandler : : loadTerrains ( )
2007-08-15 18:13:11 +03:00
{
2022-06-20 16:39:50 +02:00
for ( auto & terrain : Terrain : : Manager : : terrains ( ) )
{
terrCosts [ terrain ] = Terrain : : Manager : : getInfo ( terrain ) . moveCost ;
}
2009-06-30 15:28:22 +03:00
}
2009-07-03 21:40:36 +03:00
2013-04-21 15:49:26 +03:00
std : : vector < bool > CHeroHandler : : getDefaultAllowed ( ) const
2012-11-20 20:53:45 +03:00
{
// Look Data/HOTRAITS.txt for reference
2013-02-05 00:58:42 +03:00
std : : vector < bool > allowedHeroes ;
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
allowedHeroes . reserve ( size ( ) ) ;
2012-12-17 15:55:29 +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
for ( const CHero * hero : objects )
2012-11-20 20:53:45 +03:00
{
2012-12-17 15:55:29 +03:00
allowedHeroes . push_back ( ! hero - > special ) ;
2012-11-20 20:53:45 +03:00
}
2012-12-17 15:55:29 +03:00
2012-11-20 20:53:45 +03:00
return allowedHeroes ;
2012-12-17 15:55:29 +03:00
}