2014-11-12 10:36:34 +02:00
/*
2015-02-02 11:22:19 +02:00
* ISpellMechanics . h , part of VCMI engine
2014-11-12 10:36:34 +02:00
*
* 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
*
*/
2015-02-26 19:59:18 +02:00
2014-11-12 10:36:34 +02:00
# pragma once
2017-07-20 06:08:49 +02:00
# include "Magic.h"
# include "../battle/Destination.h"
# include "../int3.h"
# include "../GameConstants.h"
# include "../HeroBonus.h"
2015-09-17 07:42:30 +02:00
2017-07-03 20:09:27 +02:00
struct Query ;
2017-07-20 06:08:49 +02:00
class IBattleState ;
class CRandomGenerator ;
class CMap ;
class CGameInfoCallback ;
class CBattleInfoCallback ;
class JsonNode ;
class CStack ;
class CGObjectInstance ;
class CGHeroInstance ;
namespace vstd
{
class RNG ;
}
2017-07-03 20:09:27 +02:00
2015-09-16 09:50:33 +02:00
///callback to be provided by server
2017-07-20 06:08:49 +02:00
class DLL_LINKAGE SpellCastEnvironment : public spells : : PacketSender
2015-09-16 09:50:33 +02:00
{
public :
virtual ~ SpellCastEnvironment ( ) { } ;
virtual CRandomGenerator & getRandomGenerator ( ) const = 0 ;
virtual const CMap * getMap ( ) const = 0 ;
virtual const CGameInfoCallback * getCb ( ) const = 0 ;
2017-07-03 20:09:27 +02:00
virtual bool moveHero ( ObjectInstanceID hid , int3 dst , bool teleporting ) const = 0 ; //TODO: remove
virtual void genericQuery ( Query * request , PlayerColor color , std : : function < void ( const JsonNode & ) > callback ) const = 0 ; //TODO: type safety on query, use generic query packet when implemented
2015-09-16 09:50:33 +02:00
} ;
2017-07-20 06:08:49 +02:00
namespace spells
{
class DLL_LINKAGE BattleStateProxy
2015-09-16 09:50:33 +02:00
{
public :
2017-07-20 06:08:49 +02:00
const bool describe ;
BattleStateProxy ( const PacketSender * server_ ) ;
BattleStateProxy ( IBattleState * battleState_ ) ;
template < typename P >
void apply ( P * pack )
2015-09-29 20:47:04 +02:00
{
2017-07-20 06:08:49 +02:00
if ( server )
server - > sendAndApply ( pack ) ;
else
pack - > applyBattle ( battleState ) ;
}
void complain ( const std : : string & problem ) const ;
private :
const PacketSender * server ;
IBattleState * battleState ;
} ;
class DLL_LINKAGE IBattleCast
{
public :
using Value = int32_t ;
using Value64 = int64_t ;
using OptionalValue = boost : : optional < Value > ;
using OptionalValue64 = boost : : optional < Value64 > ;
virtual const CSpell * getSpell ( ) const = 0 ;
virtual Mode getMode ( ) const = 0 ;
virtual const Caster * getCaster ( ) const = 0 ;
virtual const CBattleInfoCallback * getBattle ( ) const = 0 ;
2018-03-02 12:22:51 +02:00
virtual OptionalValue getSpellLevel ( ) const = 0 ;
2017-07-20 06:08:49 +02:00
virtual OptionalValue getEffectPower ( ) const = 0 ;
virtual OptionalValue getEffectDuration ( ) const = 0 ;
virtual OptionalValue64 getEffectValue ( ) const = 0 ;
2018-02-10 06:31:02 +02:00
virtual boost : : logic : : tribool isSmart ( ) const = 0 ;
virtual boost : : logic : : tribool isMassive ( ) const = 0 ;
2017-07-20 06:08:49 +02:00
} ;
2016-02-15 12:34:37 +02:00
2017-07-20 06:08:49 +02:00
///all parameters of particular cast event
class DLL_LINKAGE BattleCast : public IBattleCast
{
public :
Target target ;
2015-09-29 20:47:04 +02:00
2018-02-10 06:31:02 +02:00
boost : : logic : : tribool smart ;
boost : : logic : : tribool massive ;
2016-09-06 12:51:53 +02:00
//normal constructor
2017-07-20 06:08:49 +02:00
BattleCast ( const CBattleInfoCallback * cb , const Caster * caster_ , const Mode mode_ , const CSpell * spell_ ) ;
2016-09-06 12:51:53 +02:00
//magic mirror constructor
2017-07-20 06:08:49 +02:00
BattleCast ( const BattleCast & orig , const Caster * caster_ ) ;
virtual ~ BattleCast ( ) ;
///IBattleCast
const CSpell * getSpell ( ) const override ;
Mode getMode ( ) const override ;
const Caster * getCaster ( ) const override ;
const CBattleInfoCallback * getBattle ( ) const override ;
2018-03-02 12:22:51 +02:00
OptionalValue getSpellLevel ( ) const override ;
2017-07-20 06:08:49 +02:00
OptionalValue getEffectPower ( ) const override ;
OptionalValue getEffectDuration ( ) const override ;
OptionalValue64 getEffectValue ( ) const override ;
2018-02-10 06:31:02 +02:00
boost : : logic : : tribool isSmart ( ) const override ;
boost : : logic : : tribool isMassive ( ) const override ;
2017-07-20 06:08:49 +02:00
void setSpellLevel ( Value value ) ;
void setEffectPower ( Value value ) ;
void setEffectDuration ( Value value ) ;
void setEffectValue ( Value64 value ) ;
2016-09-06 12:51:53 +02:00
2015-09-29 20:47:04 +02:00
void aimToHex ( const BattleHex & destination ) ;
2017-07-20 06:08:49 +02:00
void aimToUnit ( const battle : : Unit * destination ) ;
2016-09-06 12:33:11 +02:00
2017-07-20 06:08:49 +02:00
///only apply effects to specified targets
void applyEffects ( const SpellCastEnvironment * env , bool indirect = false , bool ignoreImmunity = false ) const ;
///normal cast
2016-09-06 12:33:11 +02:00
void cast ( const SpellCastEnvironment * env ) ;
2017-07-20 06:08:49 +02:00
///cast evaluation
void cast ( IBattleState * battleState , vstd : : RNG & rng ) ;
2017-03-18 13:08:02 +02:00
///cast with silent check for permitted cast
2017-06-05 20:41:27 +02:00
bool castIfPossible ( const SpellCastEnvironment * env ) ;
2017-03-18 13:08:02 +02:00
2017-07-20 06:08:49 +02:00
std : : vector < Target > findPotentialTargets ( ) const ;
private :
///spell school level
2018-03-02 12:22:51 +02:00
OptionalValue magicSkillLevel ;
2017-07-20 06:08:49 +02:00
///actual spell-power affecting effect values
OptionalValue effectPower ;
///actual spell-power affecting effect duration
OptionalValue effectDuration ;
2016-02-15 12:34:37 +02:00
2017-07-20 06:08:49 +02:00
///for Archangel-like casting
OptionalValue64 effectValue ;
2016-09-18 14:27:22 +02:00
2017-07-20 06:08:49 +02:00
Mode mode ;
2016-09-06 12:33:11 +02:00
const CSpell * spell ;
2017-07-20 06:08:49 +02:00
const CBattleInfoCallback * cb ;
const Caster * caster ;
} ;
2015-09-17 08:29:57 +02:00
2017-07-20 06:08:49 +02:00
class DLL_LINKAGE ISpellMechanicsFactory
{
public :
virtual ~ ISpellMechanicsFactory ( ) ;
2015-09-29 20:47:04 +02:00
2017-07-20 06:08:49 +02:00
virtual std : : unique_ptr < Mechanics > create ( const IBattleCast * event ) const = 0 ;
2015-09-17 07:42:30 +02:00
2017-07-20 06:08:49 +02:00
static std : : unique_ptr < ISpellMechanicsFactory > get ( const CSpell * s ) ;
2016-09-18 14:27:22 +02:00
2017-07-20 06:08:49 +02:00
protected :
const CSpell * spell ;
ISpellMechanicsFactory ( const CSpell * s ) ;
} ;
class DLL_LINKAGE Mechanics
{
public :
Mechanics ( ) ;
virtual ~ Mechanics ( ) ;
virtual bool adaptProblem ( ESpellCastProblem : : ESpellCastProblem source , Problem & target ) const = 0 ;
virtual bool adaptGenericProblem ( Problem & target ) const = 0 ;
virtual std : : vector < BattleHex > rangeInHexes ( BattleHex centralHex , bool * outDroppedHexes = nullptr ) const = 0 ;
virtual std : : vector < const CStack * > getAffectedStacks ( const Target & target ) const = 0 ;
virtual bool canBeCast ( Problem & problem ) const = 0 ;
virtual bool canBeCastAt ( const Target & target ) const = 0 ;
virtual void applyEffects ( BattleStateProxy * battleState , vstd : : RNG & rng , const Target & targets , bool indirect , bool ignoreImmunity ) const = 0 ;
virtual void cast ( const PacketSender * server , vstd : : RNG & rng , const Target & target ) = 0 ;
virtual void cast ( IBattleState * battleState , vstd : : RNG & rng , const Target & target ) = 0 ;
virtual bool isReceptive ( const battle : : Unit * target ) const = 0 ;
virtual std : : vector < AimType > getTargetTypes ( ) const = 0 ;
virtual std : : vector < Destination > getPossibleDestinations ( size_t index , AimType aimType , const Target & current ) const = 0 ;
//Cast event facade
virtual IBattleCast : : Value getEffectLevel ( ) const = 0 ;
virtual IBattleCast : : Value getRangeLevel ( ) const = 0 ;
virtual IBattleCast : : Value getEffectPower ( ) const = 0 ;
virtual IBattleCast : : Value getEffectDuration ( ) const = 0 ;
virtual IBattleCast : : Value64 getEffectValue ( ) const = 0 ;
virtual PlayerColor getCasterColor ( ) const = 0 ;
//Spell facade
virtual int32_t getSpellIndex ( ) const = 0 ;
virtual SpellID getSpellId ( ) const = 0 ;
virtual std : : string getSpellName ( ) const = 0 ;
virtual int32_t getSpellLevel ( ) const = 0 ;
virtual bool isSmart ( ) const = 0 ;
virtual bool isMassive ( ) const = 0 ;
virtual bool alwaysHitFirstTarget ( ) const = 0 ;
virtual bool requiresClearTiles ( ) const = 0 ;
virtual bool isNegativeSpell ( ) const = 0 ;
virtual bool isPositiveSpell ( ) const = 0 ;
virtual int64_t adjustEffectValue ( const battle : : Unit * target ) const = 0 ;
virtual int64_t applySpellBonus ( int64_t value , const battle : : Unit * target ) const = 0 ;
virtual int64_t applySpecificSpellBonus ( int64_t value ) const = 0 ;
virtual int64_t calculateRawEffectValue ( int32_t basePowerMultiplier , int32_t levelPowerMultiplier ) const = 0 ;
virtual std : : vector < Bonus : : BonusType > getElementalImmunity ( ) const = 0 ;
//Battle facade
virtual bool ownerMatches ( const battle : : Unit * unit ) const = 0 ;
virtual bool ownerMatches ( const battle : : Unit * unit , const boost : : logic : : tribool positivness ) const = 0 ;
const CBattleInfoCallback * cb ;
const Caster * caster ;
ui8 casterSide ;
2015-09-16 09:50:33 +02:00
} ;
2017-07-20 06:08:49 +02:00
class DLL_LINKAGE BaseMechanics : public Mechanics
2016-09-04 04:15:37 +02:00
{
2014-11-13 06:34:20 +02:00
public :
2017-07-20 06:08:49 +02:00
BaseMechanics ( const IBattleCast * event ) ;
virtual ~ BaseMechanics ( ) ;
bool adaptProblem ( ESpellCastProblem : : ESpellCastProblem source , Problem & target ) const override ;
bool adaptGenericProblem ( Problem & target ) const override ;
2015-02-26 19:59:18 +02:00
2017-07-20 06:08:49 +02:00
int32_t getSpellIndex ( ) const override ;
SpellID getSpellId ( ) const override ;
std : : string getSpellName ( ) const override ;
int32_t getSpellLevel ( ) const override ;
2016-02-15 12:34:37 +02:00
2017-07-20 06:08:49 +02:00
IBattleCast : : Value getEffectLevel ( ) const override ;
IBattleCast : : Value getRangeLevel ( ) const override ;
2016-02-15 12:34:37 +02:00
2017-07-20 06:08:49 +02:00
IBattleCast : : Value getEffectPower ( ) const override ;
IBattleCast : : Value getEffectDuration ( ) const override ;
2016-03-01 08:50:04 +02:00
2017-07-20 06:08:49 +02:00
IBattleCast : : Value64 getEffectValue ( ) const override ;
2016-02-15 12:34:37 +02:00
2017-07-20 06:08:49 +02:00
PlayerColor getCasterColor ( ) const override ;
2015-02-26 19:59:18 +02:00
2017-07-20 06:08:49 +02:00
bool isSmart ( ) const override ;
bool isMassive ( ) const override ;
bool requiresClearTiles ( ) const override ;
bool alwaysHitFirstTarget ( ) const override ;
bool isNegativeSpell ( ) const override ;
bool isPositiveSpell ( ) const override ;
int64_t adjustEffectValue ( const battle : : Unit * target ) const override ;
int64_t applySpellBonus ( int64_t value , const battle : : Unit * target ) const override ;
int64_t applySpecificSpellBonus ( int64_t value ) const override ;
int64_t calculateRawEffectValue ( int32_t basePowerMultiplier , int32_t levelPowerMultiplier ) const override ;
std : : vector < Bonus : : BonusType > getElementalImmunity ( ) const override ;
bool ownerMatches ( const battle : : Unit * unit ) const override ;
bool ownerMatches ( const battle : : Unit * unit , const boost : : logic : : tribool positivness ) const override ;
std : : vector < AimType > getTargetTypes ( ) const override ;
2016-09-05 10:36:25 +02:00
2016-09-04 07:19:28 +02:00
protected :
2017-06-06 06:53:51 +02:00
const CSpell * owner ;
2017-07-20 06:08:49 +02:00
Mode mode ;
2018-02-10 06:31:02 +02:00
private :
2017-07-20 06:08:49 +02:00
IBattleCast : : Value rangeLevel ;
IBattleCast : : Value effectLevel ;
///actual spell-power affecting effect values
IBattleCast : : Value effectPower ;
///actual spell-power affecting effect duration
IBattleCast : : Value effectDuration ;
///raw damage/heal amount
IBattleCast : : Value64 effectValue ;
2018-02-10 06:31:02 +02:00
boost : : logic : : tribool smart ;
boost : : logic : : tribool massive ;
2017-07-20 06:08:49 +02:00
} ;
class DLL_LINKAGE IReceptiveCheck
{
public :
virtual ~ IReceptiveCheck ( ) = default ;
virtual bool isReceptive ( const Mechanics * m , const battle : : Unit * target ) const = 0 ;
2016-09-04 07:19:28 +02:00
} ;
2017-07-20 06:08:49 +02:00
} // namespace spells
class DLL_LINKAGE AdventureSpellCastParameters
2016-09-04 07:19:28 +02:00
{
2017-07-20 06:08:49 +02:00
public :
2016-09-04 07:19:28 +02:00
const CGHeroInstance * caster ;
int3 pos ;
} ;
class DLL_LINKAGE IAdventureSpellMechanics
{
public :
2017-06-06 06:53:51 +02:00
IAdventureSpellMechanics ( const CSpell * s ) ;
2016-09-04 07:19:28 +02:00
virtual ~ IAdventureSpellMechanics ( ) = default ;
2017-07-03 20:09:27 +02:00
virtual bool adventureCast ( const SpellCastEnvironment * env , const AdventureSpellCastParameters & parameters ) const = 0 ;
2016-09-04 07:19:28 +02:00
2017-06-06 06:53:51 +02:00
static std : : unique_ptr < IAdventureSpellMechanics > createMechanics ( const CSpell * s ) ;
2014-11-13 06:34:20 +02:00
protected :
2017-06-06 06:53:51 +02:00
const CSpell * owner ;
2014-11-13 06:34:20 +02:00
} ;