2011-12-14 00:23:17 +03:00
# pragma once
2009-04-16 14:14:13 +03:00
2014-03-07 16:21:09 +03:00
# include "IHandlerBase.h"
2010-12-19 16:39:56 +02:00
# include "../lib/ConstTransitivePtr.h"
2011-12-14 00:23:17 +03:00
# include "int3.h"
# include "GameConstants.h"
2014-11-13 03:53:25 +02:00
# include "BattleHex.h"
2013-01-15 17:20:48 +03:00
# include "HeroBonus.h"
2009-05-14 07:49:04 +03:00
2014-03-07 16:21:09 +03:00
2009-04-15 17:03:31 +03:00
/*
* CSpellHandler . h , 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
*
2009-04-16 14:14:13 +03:00
*/
2014-11-12 05:59:53 +02:00
class CSpell ;
2014-11-13 03:53:25 +02:00
class ISpellMechanics ;
class CLegacyConfigParser ;
2014-11-12 05:59:53 +02:00
class CGHeroInstance ;
class CStack ;
2014-11-13 03:53:25 +02:00
class CBattleInfoCallback ;
2014-11-12 10:36:34 +02:00
struct CPackForClient ;
2014-11-12 10:03:55 +02:00
struct SpellSchoolInfo
{
ESpellSchool id ; //backlink
Bonus : : BonusType damagePremyBonus ;
Bonus : : BonusType immunityBonus ;
std : : string jsonName ;
} ;
static SpellSchoolInfo spellSchoolConfig [ 4 ] =
{
{
ESpellSchool : : AIR ,
Bonus : : AIR_SPELL_DMG_PREMY ,
Bonus : : AIR_IMMUNITY ,
" air "
} ,
{
ESpellSchool : : FIRE ,
Bonus : : FIRE_SPELL_DMG_PREMY ,
Bonus : : FIRE_IMMUNITY ,
" fire "
} ,
{
ESpellSchool : : WATER ,
Bonus : : WATER_SPELL_DMG_PREMY ,
Bonus : : WATER_IMMUNITY ,
" water "
} ,
{
ESpellSchool : : EARTH ,
Bonus : : EARTH_SPELL_DMG_PREMY ,
Bonus : : EARTH_IMMUNITY ,
" earth "
}
} ;
2014-11-12 10:36:34 +02:00
///callback to be provided by server
class DLL_LINKAGE SpellCastEnvironment
{
public :
virtual void sendAndApply ( CPackForClient * info ) = 0 ;
} ;
///helper struct
struct DLL_LINKAGE SpellCastContext
{
public :
SpellCastEnvironment * env ;
2014-11-13 03:53:25 +02:00
int spellLvl ;
// BattleHex destination;
ui8 casterSide ;
PlayerColor casterColor ;
CGHeroInstance * caster ;
CGHeroInstance * secHero ;
int usedSpellPower ;
ECastingMode : : ECastingMode mode ;
CStack * targetStack ;
CStack * selectedStack ;
2014-11-12 05:59:53 +02:00
} ;
2012-05-18 23:50:16 +03:00
2014-11-13 03:53:25 +02:00
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CSpell
2009-04-16 14:14:13 +03:00
{
2014-03-07 16:21:09 +03:00
public :
2014-05-01 01:48:33 +03:00
struct LevelInfo
{
std : : string description ; //descriptions of spell for skill level
si32 cost ; //per skill level: 0 - none, 1 - basic, etc
si32 power ; //per skill level: 0 - none, 1 - basic, etc
si32 AIValue ; //AI values: per skill level: 0 - none, 1 - basic, etc
bool smartTarget ;
std : : string range ;
std : : vector < Bonus > effects ;
LevelInfo ( ) ;
~ LevelInfo ( ) ;
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & description & cost & power & AIValue & smartTarget & range & effects ;
}
} ;
/** \brief Low level accessor. Don`t use it if absolutely necessary
*
* \ param level . spell school level
* \ return Spell level info structure
*
*/
const CSpell : : LevelInfo & getLevelInfo ( const int level ) const ;
2009-04-16 14:14:13 +03:00
public :
2014-03-17 16:11:10 +03:00
enum ETargetType { NO_TARGET , CREATURE , OBSTACLE } ;
2012-02-17 00:19:07 +03:00
enum ESpellPositiveness { NEGATIVE = - 1 , NEUTRAL = 0 , POSITIVE = 1 } ;
2014-03-17 16:11:10 +03:00
struct TargetInfo
{
2014-05-01 01:48:33 +03:00
ETargetType type ;
bool smart ;
bool massive ;
2014-05-18 12:20:36 +03:00
bool onlyAlive ;
2014-11-13 03:53:25 +02:00
///no immunity on primary target (mostly spell-like attack)
bool alwaysHitDirectly ;
2014-03-17 16:11:10 +03:00
} ;
2013-02-11 02:24:57 +03:00
SpellID id ;
2014-03-07 16:21:09 +03:00
std : : string identifier ; //???
2009-04-16 14:14:13 +03:00
std : : string name ;
2014-03-17 16:11:10 +03:00
2009-04-16 14:14:13 +03:00
si32 level ;
2014-11-12 10:03:55 +02:00
bool earth ; //deprecated
bool water ; //deprecated
bool fire ; //deprecated
bool air ; //deprecated
std : : map < ESpellSchool , bool > school ; //todo: use this instead of separate boolean fields
2009-04-16 14:14:13 +03:00
si32 power ; //spell's power
2014-03-07 16:21:09 +03:00
2012-12-18 13:32:11 +03:00
std : : map < TFaction , si32 > probabilities ; //% chance to gain for castles
2013-02-13 22:35:43 +03:00
2009-04-16 14:14:13 +03:00
bool combatSpell ; //is this spell combat (true) or adventure (false)
bool creatureAbility ; //if true, only creatures can use this spell
si8 positiveness ; //1 if spell is positive for influenced stacks, 0 if it is indifferent, -1 if it's negative
2014-03-17 16:11:10 +03:00
2013-02-11 02:24:57 +03:00
std : : vector < SpellID > counteredSpells ; //spells that are removed when effect of this spell is placed on creature (for bless-curse, haste-slow, and similar pairs)
2012-09-14 02:41:03 +03:00
2013-01-15 17:20:48 +03:00
CSpell ( ) ;
2013-04-21 19:38:31 +03:00
~ CSpell ( ) ;
2013-01-15 17:20:48 +03:00
2013-06-26 14:18:27 +03:00
std : : vector < BattleHex > rangeInHexes ( BattleHex centralHex , ui8 schoolLvl , ui8 side , bool * outDroppedHexes = nullptr ) const ; //convert range to specific hexes; last optional out parameter is set to true, if spell would cover unavailable hexes (that are not included in ret)
2009-04-22 13:03:13 +03:00
si16 mainEffectAnim ; //main spell effect animation, in AC format (or -1 when none)
2014-03-17 16:11:10 +03:00
ETargetType getTargetType ( ) const ; //deprecated
2014-11-13 03:53:25 +02:00
CSpell : : TargetInfo getTargetInfo ( const int level ) const ;
CSpell : : TargetInfo getTargetInfoEx ( const int level , ECastingMode : : ECastingMode mode ) const ;
2009-04-16 14:14:13 +03:00
2014-03-09 02:18:51 +03:00
bool isCombatSpell ( ) const ;
bool isAdventureSpell ( ) const ;
bool isCreatureAbility ( ) const ;
2013-02-02 20:20:31 +03:00
2014-03-09 02:18:51 +03:00
bool isPositive ( ) const ;
bool isNegative ( ) const ;
2014-05-17 13:36:49 +03:00
bool isNeutral ( ) const ;
2013-02-02 20:20:31 +03:00
2014-03-09 02:18:51 +03:00
bool isDamageSpell ( ) const ;
2014-11-12 07:34:43 +02:00
bool isHealingSpell ( ) const ;
bool isRisingSpell ( ) const ;
2014-03-09 02:18:51 +03:00
bool isOffensiveSpell ( ) const ;
2013-02-02 20:20:31 +03:00
2014-03-09 02:18:51 +03:00
bool isSpecialSpell ( ) const ;
2014-03-07 19:10:20 +03:00
2014-03-09 02:18:51 +03:00
bool hasEffects ( ) const ;
2013-01-16 14:19:04 +03:00
void getEffects ( std : : vector < Bonus > & lst , const int level ) const ;
2014-11-12 06:41:12 +02:00
//internal, for use only by Mechanics classes
2014-11-12 04:50:51 +02:00
ESpellCastProblem : : ESpellCastProblem isImmuneBy ( const IBonusBearer * obj ) const ;
2014-11-12 05:59:53 +02:00
//checks for creature immunity / anything that prevent casting *at given hex* - doesn't take into acount general problems such as not having spellbook or mana points etc.
2014-11-13 03:53:25 +02:00
ESpellCastProblem : : ESpellCastProblem isImmuneByStack ( const CGHeroInstance * caster , const CStack * obj ) const ;
2014-11-12 07:02:27 +02:00
2014-11-12 08:52:11 +02:00
//internal, for use only by Mechanics classes. applying secondary skills
2014-11-12 07:02:27 +02:00
ui32 calculateBonus ( ui32 baseDamage , const CGHeroInstance * caster , const CStack * affectedCreature ) const ;
2014-11-12 07:34:43 +02:00
2014-11-12 08:52:11 +02:00
ui32 calculateDamage ( const CGHeroInstance * caster , const CStack * affectedCreature , int spellSchoolLevel , int usedSpellPower ) const ;
2014-11-12 07:34:43 +02:00
///calculate healed HP for all spells casted by hero
ui32 calculateHealedHP ( const CGHeroInstance * caster , const CStack * stack , const CStack * sacrificedStack = nullptr ) const ;
2014-11-12 08:52:11 +02:00
2014-11-13 03:53:25 +02:00
///selects from allStacks actually affected stacks
std : : set < const CStack * > getAffectedStacks ( const CBattleInfoCallback * cb , ECastingMode : : ECastingMode mode , PlayerColor casterColor , int spellLvl , BattleHex destination , const CGHeroInstance * caster = nullptr ) const ;
2012-02-17 00:19:07 +03:00
2014-03-09 02:18:51 +03:00
si32 getCost ( const int skillLevel ) const ;
2014-03-07 16:21:09 +03:00
2014-05-01 01:48:33 +03:00
/**
* Returns spell level power , base power ignored
*/
2014-03-09 02:18:51 +03:00
si32 getPower ( const int skillLevel ) const ;
2014-03-07 16:21:09 +03:00
2014-05-01 01:48:33 +03:00
// /**
2014-03-07 16:21:09 +03:00
// * Returns spell power, taking base power into account
// */
2014-03-09 02:18:51 +03:00
// si32 calculatePower(const int skillLevel) const;
2014-03-07 16:21:09 +03:00
2014-03-09 02:18:51 +03:00
si32 getProbability ( const TFaction factionId ) const ;
2014-03-07 16:21:09 +03:00
2013-02-13 22:35:43 +03:00
/**
2014-05-01 01:48:33 +03:00
* Returns resource name of icon for SPELL_IMMUNITY bonus
*/
2014-03-09 02:18:51 +03:00
const std : : string & getIconImmune ( ) const ;
2014-03-17 16:11:10 +03:00
2014-03-10 19:00:58 +03:00
const std : : string & getCastSound ( ) const ;
2013-02-13 22:35:43 +03:00
2009-04-16 14:14:13 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2014-03-17 16:11:10 +03:00
h & identifier & id & name & level & earth & water & fire & air & power
2014-05-01 01:48:33 +03:00
& probabilities & attributes & combatSpell & creatureAbility & positiveness & counteredSpells & mainEffectAnim ;
2013-02-13 22:35:43 +03:00
h & isRising & isDamage & isOffensive ;
h & targetType ;
2014-05-18 16:55:26 +03:00
h & immunities & limiters & absoluteImmunities & absoluteLimiters ;
2013-02-13 22:35:43 +03:00
h & iconImmune ;
2014-05-18 16:55:26 +03:00
h & defaultProbability ;
2014-03-07 19:10:20 +03:00
2014-05-01 01:48:33 +03:00
h & isSpecial ;
2014-03-17 16:11:10 +03:00
2014-05-01 01:48:33 +03:00
h & castSound & iconBook & iconEffect & iconScenarioBonus & iconScroll ;
2014-03-17 16:11:10 +03:00
2014-05-01 01:48:33 +03:00
h & levels ;
2014-11-12 05:59:53 +02:00
if ( ! h . saving )
2014-11-12 10:03:55 +02:00
setup ( ) ;
2009-04-16 14:14:13 +03:00
}
2013-01-15 17:20:48 +03:00
friend class CSpellHandler ;
2014-03-10 19:00:58 +03:00
friend class Graphics ;
2013-01-15 17:20:48 +03:00
private :
2014-05-01 01:48:33 +03:00
void setIsOffensive ( const bool val ) ;
void setIsRising ( const bool val ) ;
2014-11-12 05:59:53 +02:00
//call this after load or deserialization. cant be done in constructor.
2014-11-12 10:03:55 +02:00
void setup ( ) ;
2014-11-12 05:59:53 +02:00
void setupMechanics ( ) ;
2014-03-07 16:21:09 +03:00
private :
2014-05-01 01:48:33 +03:00
si32 defaultProbability ;
2013-02-13 22:35:43 +03:00
2013-01-16 14:19:04 +03:00
bool isRising ;
bool isDamage ;
bool isOffensive ;
2014-03-07 19:10:20 +03:00
bool isSpecial ;
2013-01-15 17:20:48 +03:00
2014-03-07 16:21:09 +03:00
std : : string attributes ; //reference only attributes //todo: remove or include in configuration format, currently unused
2013-02-13 22:35:43 +03:00
ETargetType targetType ;
std : : vector < Bonus : : BonusType > immunities ; //any of these grants immunity
2014-03-23 15:59:03 +03:00
std : : vector < Bonus : : BonusType > absoluteImmunities ; //any of these grants immunity, can't be negated
2013-02-13 22:35:43 +03:00
std : : vector < Bonus : : BonusType > limiters ; //all of them are required to be affected
2014-05-18 16:55:26 +03:00
std : : vector < Bonus : : BonusType > absoluteLimiters ; //all of them are required to be affected, can't be negated
2013-02-02 20:20:31 +03:00
2013-02-13 22:35:43 +03:00
///graphics related stuff
2013-01-15 17:20:48 +03:00
2013-02-13 22:35:43 +03:00
std : : string iconImmune ;
2014-03-17 16:11:10 +03:00
2014-03-10 19:00:58 +03:00
std : : string iconBook ;
std : : string iconEffect ;
2014-03-17 16:11:10 +03:00
std : : string iconScenarioBonus ;
2014-03-10 19:00:58 +03:00
std : : string iconScroll ;
///sound related stuff
std : : string castSound ;
2014-03-17 16:11:10 +03:00
std : : vector < LevelInfo > levels ;
2014-11-12 05:59:53 +02:00
2014-11-12 10:36:34 +02:00
ISpellMechanics * mechanics ; //(!) do not serialize
2009-04-16 14:14:13 +03:00
} ;
2014-11-13 03:53:25 +02:00
class DLL_LINKAGE ISpellMechanics
{
public :
struct SpellTargetingContext
{
CBattleInfoCallback * cb ;
CSpell : : TargetInfo ti ;
} ;
public :
ISpellMechanics ( CSpell * s ) ;
virtual ~ ISpellMechanics ( ) { } ;
virtual std : : set < const CStack * > getAffectedStacks ( SpellTargetingContext & ctx ) const = 0 ;
virtual ESpellCastProblem : : ESpellCastProblem isImmuneByStack ( const CGHeroInstance * caster , const CStack * obj ) const = 0 ;
/** \brief
*
* \ param
* \ return true if no error
*
*/
virtual bool adventureCast ( SpellCastContext & context ) const = 0 ;
virtual bool battleCast ( SpellCastContext & context ) const = 0 ;
protected :
CSpell * owner ;
} ;
2014-03-07 16:21:09 +03:00
2013-02-13 22:35:43 +03:00
2011-12-14 00:23:17 +03:00
bool DLL_LINKAGE isInScreenRange ( const int3 & center , const int3 & pos ) ; //for spells like Dimension Door
2010-03-21 00:17:19 +02:00
2014-03-07 16:21:09 +03:00
class DLL_LINKAGE CSpellHandler : public CHandlerBase < SpellID , CSpell >
2009-04-16 14:14:13 +03:00
{
public :
2009-09-25 06:21:56 +03:00
CSpellHandler ( ) ;
2014-03-07 16:21:09 +03:00
virtual ~ CSpellHandler ( ) ;
2014-05-01 01:48:33 +03:00
///IHandler base
std : : vector < JsonNode > loadLegacyData ( size_t dataSize ) override ;
void afterLoadFinalization ( ) override ;
2014-05-18 17:47:18 +03:00
void beforeValidate ( JsonNode & object ) override ;
2013-01-15 17:20:48 +03:00
2013-01-06 22:30:12 +03:00
/**
* Gets a list of default allowed spells . OH3 spells are all allowed by default .
*
* @ return a list of allowed spells , the index is the spell id and the value either 0 for not allowed or 1 for allowed
*/
2014-03-07 16:21:09 +03:00
std : : vector < bool > getDefaultAllowed ( ) const override ;
2014-03-08 22:02:47 +03:00
const std : : string getTypeName ( ) const override ;
2013-01-06 22:30:12 +03:00
2009-04-16 14:14:13 +03:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2014-03-07 16:21:09 +03:00
h & objects ;
2009-04-16 14:14:13 +03:00
}
2014-03-07 16:21:09 +03:00
protected :
2014-05-01 01:48:33 +03:00
CSpell * loadFromJson ( const JsonNode & json ) override ;
2009-04-16 14:14:13 +03:00
} ;