2012-08-26 12:07:48 +03:00
# pragma once
# include "BattleHex.h"
2012-12-19 17:54:10 +03:00
/*
* CBattleCallback . 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
*
*/
2012-08-26 12:07:48 +03:00
class CGameState ;
class CGTownInstance ;
class CGHeroInstance ;
class CStack ;
2015-09-28 15:06:26 +02:00
class ISpellCaster ;
2012-08-26 12:07:48 +03:00
class CSpell ;
struct BattleInfo ;
struct CObstacleInstance ;
2012-09-20 19:55:21 +03:00
class IBonusBearer ;
2012-09-24 02:10:56 +03:00
struct InfoAboutHero ;
2013-07-22 01:01:29 +03:00
class CArmedInstance ;
2016-09-09 19:30:36 +02:00
class CRandomGenerator ;
2012-08-26 12:07:48 +03:00
namespace boost
{ class shared_mutex ; }
namespace BattleSide
{
enum { ATTACKER = 0 , DEFENDER = 1 } ;
}
typedef std : : vector < const CStack * > TStacks ;
2014-05-17 12:37:12 +03:00
typedef std : : function < bool ( const CStack * ) > TStackFilter ;
2012-08-26 12:07:48 +03:00
class CBattleInfoEssentials ;
//Basic class for various callbacks (interfaces called by players to get info about game and so forth)
class DLL_LINKAGE CCallbackBase
{
2013-06-26 14:18:27 +03:00
const BattleInfo * battle ; //battle to which the player is engaged, nullptr if none or not applicable
2012-08-26 12:07:48 +03:00
const BattleInfo * getBattle ( ) const
{
return battle ;
}
protected :
CGameState * gs ;
2013-03-03 20:06:03 +03:00
boost : : optional < PlayerColor > player ; // not set gives access to all information, otherwise callback provides only information "visible" for player
2012-08-26 12:07:48 +03:00
2013-03-03 20:06:03 +03:00
CCallbackBase ( CGameState * GS , boost : : optional < PlayerColor > Player )
2012-08-27 13:47:02 +03:00
: battle ( nullptr ) , gs ( GS ) , player ( Player )
2012-08-26 12:07:48 +03:00
{ }
CCallbackBase ( )
2013-02-11 17:42:09 +03:00
: battle ( nullptr ) , gs ( nullptr )
2012-08-26 12:07:48 +03:00
{ }
2016-02-28 04:10:20 +02:00
2012-08-26 12:07:48 +03:00
void setBattle ( const BattleInfo * B ) ;
bool duringBattle ( ) const ;
public :
boost : : shared_mutex & getGsMutex ( ) ; //just return a reference to mutex, does not lock nor anything
2013-03-03 20:06:03 +03:00
boost : : optional < PlayerColor > getPlayerID ( ) const ;
2012-08-26 12:07:48 +03:00
friend class CBattleInfoEssentials ;
} ;
struct DLL_LINKAGE AttackableTiles
{
std : : set < BattleHex > hostileCreaturePositions ;
std : : set < BattleHex > friendlyCreaturePositions ; //for Dragon Breath
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & hostileCreaturePositions & friendlyCreaturePositions ;
}
} ;
//Accessibility is property of hex in battle. It doesn't depend on stack, side's perspective and so on.
namespace EAccessibility
{
enum EAccessibility
{
2016-02-28 04:10:20 +02:00
ACCESSIBLE ,
ALIVE_STACK ,
2012-08-26 12:07:48 +03:00
OBSTACLE ,
DESTRUCTIBLE_WALL ,
GATE , //sieges -> gate opens only for defender stacks
UNAVAILABLE , //indestructible wall parts, special battlefields (like boat-to-boat)
SIDE_COLUMN //used for first and last columns of hexes that are unavailable but wat machines can stand there
} ;
}
typedef std : : array < EAccessibility : : EAccessibility , GameConstants : : BFIELD_SIZE > TAccessibilityArray ;
struct DLL_LINKAGE AccessibilityInfo : TAccessibilityArray
{
bool occupiable ( const CStack * stack , BattleHex tile ) const ;
bool accessible ( BattleHex tile , const CStack * stack ) const ; //checks for both tiles if stack is double wide
bool accessible ( BattleHex tile , bool doubleWide , bool attackerOwned ) const ; //checks for both tiles if stack is double wide
} ;
namespace BattlePerspective
{
enum BattlePerspective
{
INVALID = - 2 ,
ALL_KNOWING = - 1 ,
LEFT_SIDE ,
RIGHT_SIDE
} ;
}
2014-03-23 15:59:03 +03:00
// Reachability info is result of BFS calculation. It's dependent on stack (it's owner, whether it's flying),
2012-08-26 12:07:48 +03:00
// startPosition and perpective.
struct DLL_LINKAGE ReachabilityInfo
{
typedef std : : array < int , GameConstants : : BFIELD_SIZE > TDistances ;
typedef std : : array < BattleHex , GameConstants : : BFIELD_SIZE > TPredecessors ;
2012-08-26 22:13:57 +03:00
enum { INFINITE_DIST = 1000000 } ;
2012-08-26 12:07:48 +03:00
struct DLL_LINKAGE Parameters
{
const CStack * stack ; //stack for which calculation is mage => not required (kept for debugging mostly), following variables are enough
2016-02-28 04:10:20 +02:00
2012-08-26 12:07:48 +03:00
bool attackerOwned ;
bool doubleWide ;
bool flying ;
2012-08-28 15:28:13 +03:00
std : : vector < BattleHex > knownAccessible ; //hexes that will be treated as accessible, even if they're occupied by stack (by default - tiles occupied by stack we do reachability for, so it doesn't block itself)
2012-08-26 12:07:48 +03:00
BattleHex startPosition ; //assumed position of stack
BattlePerspective : : BattlePerspective perspective ; //some obstacles (eg. quicksands) may be invisible for some side
Parameters ( ) ;
Parameters ( const CStack * Stack ) ;
} ;
Parameters params ;
AccessibilityInfo accessibility ;
TDistances distances ;
TPredecessors predecessors ;
ReachabilityInfo ( )
{
2012-08-26 22:13:57 +03:00
distances . fill ( INFINITE_DIST ) ;
2012-08-26 12:07:48 +03:00
predecessors . fill ( BattleHex : : INVALID ) ;
}
bool isReachable ( BattleHex hex ) const
{
2012-08-28 15:28:13 +03:00
return distances [ hex ] < INFINITE_DIST ;
2012-08-26 12:07:48 +03:00
}
} ;
class DLL_LINKAGE CBattleInfoEssentials : public virtual CCallbackBase
{
protected :
bool battleDoWeKnowAbout ( ui8 side ) const ;
2015-09-16 17:28:14 +02:00
const IBonusBearer * getBattleNode ( ) const ;
2012-08-26 12:07:48 +03:00
public :
enum EStackOwnership
{
ONLY_MINE , ONLY_ENEMY , MINE_AND_ENEMY
} ;
BattlePerspective : : BattlePerspective battleGetMySide ( ) const ;
2013-02-13 01:24:48 +03:00
ETerrainType battleTerrainType ( ) const ;
BFieldType battleGetBattlefieldType ( ) const ;
2015-12-29 04:43:33 +02:00
std : : vector < std : : shared_ptr < const CObstacleInstance > > battleGetAllObstacles ( boost : : optional < BattlePerspective : : BattlePerspective > perspective = boost : : none ) const ; //returns all obstacles on the battlefield
2016-02-28 04:10:20 +02:00
2014-05-17 12:37:12 +03:00
/** @brief Main method for getting battle stacks
*
* @ param predicate Functor that shall return true for desired stack
* @ return filtered stacks
*
2016-02-28 04:10:20 +02:00
*/
TStacks battleGetStacksIf ( TStackFilter predicate ) const ;
2012-08-26 12:07:48 +03:00
bool battleHasNativeStack ( ui8 side ) const ;
int battleGetMoatDmg ( ) const ; //what dmg unit will suffer if ending turn in the moat
2013-06-26 14:18:27 +03:00
const CGTownInstance * battleGetDefendedTown ( ) const ; //returns defended town if current battle is a siege, nullptr instead
2012-08-26 12:07:48 +03:00
const CStack * battleActiveStack ( ) const ;
si8 battleTacticDist ( ) const ; //returns tactic distance in current tactics phase; 0 if not in tactics phase
si8 battleGetTacticsSide ( ) const ; //returns which side is in tactics phase, undefined if none (?)
2013-03-03 20:06:03 +03:00
bool battleCanFlee ( PlayerColor player ) const ;
bool battleCanSurrender ( PlayerColor player ) const ;
2016-11-28 02:33:39 +02:00
si8 playerToSide ( PlayerColor player ) const ;
2016-09-28 13:22:33 +02:00
bool playerHasAccessToHeroInfo ( PlayerColor player , const CGHeroInstance * h ) const ;
2012-08-26 12:07:48 +03:00
ui8 battleGetSiegeLevel ( ) const ; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
bool battleHasHero ( ui8 side ) const ;
2015-09-21 11:19:35 +02:00
int battleCastSpells ( ui8 side ) const ; //how many spells has given side cast
2013-01-20 23:29:35 +03:00
const CGHeroInstance * battleGetFightingHero ( ui8 side ) const ; //depracated for players callback, easy to get wrong
2016-02-28 04:10:20 +02:00
const CArmedInstance * battleGetArmyObject ( ui8 side ) const ;
2013-01-20 23:29:35 +03:00
InfoAboutHero battleGetHeroInfo ( ui8 side ) const ;
2012-08-26 12:07:48 +03:00
2013-12-08 20:54:13 +03:00
// for determining state of a part of the wall; format: parameter [0] - keep, [1] - bottom tower, [2] - bottom wall,
// [3] - below gate, [4] - over gate, [5] - upper wall, [6] - uppert tower, [7] - gate; returned value: 1 - intact, 2 - damaged, 3 - destroyed; 0 - no battle
si8 battleGetWallState ( int partOfWall ) const ;
2016-02-13 16:40:31 +02:00
EGateState battleGetGateState ( ) const ;
2013-12-08 20:54:13 +03:00
2012-08-26 12:07:48 +03:00
//helpers
2014-05-17 12:37:12 +03:00
///returns all stacks, alive or dead or undead or mechanical :)
TStacks battleGetAllStacks ( bool includeTurrets = false ) const ;
2016-02-28 04:10:20 +02:00
2014-05-17 12:37:12 +03:00
///returns all alive stacks excluding turrets
2012-08-26 12:07:48 +03:00
TStacks battleAliveStacks ( ) const ;
2014-05-17 12:37:12 +03:00
///returns all alive stacks from particular side excluding turrets
2012-08-26 12:07:48 +03:00
TStacks battleAliveStacks ( ui8 side ) const ;
const CStack * battleGetStackByID ( int ID , bool onlyAlive = true ) const ; //returns stack info by given ID
bool battleIsObstacleVisibleForSide ( const CObstacleInstance & coi , BattlePerspective : : BattlePerspective side ) const ;
2016-09-29 20:47:41 +02:00
2016-09-29 21:26:28 +02:00
///returns player that controls given stack; mind control included
PlayerColor battleGetOwner ( const CStack * stack ) const ;
///returns hero that controls given stack; nullptr if none; mind control included
const CGHeroInstance * battleGetOwnerHero ( const CStack * stack ) const ;
///check that stacks are controlled by same|other player(s) depending on positiveness
///mind control included
bool battleMatchOwner ( const CStack * attacker , const CStack * defender , const boost : : logic : : tribool positivness = false ) const ;
2012-08-26 12:07:48 +03:00
} ;
2012-09-20 19:55:21 +03:00
struct DLL_LINKAGE BattleAttackInfo
{
const IBonusBearer * attackerBonuses , * defenderBonuses ;
const CStack * attacker , * defender ;
BattleHex attackerPosition , defenderPosition ;
2013-06-21 23:59:32 +03:00
int attackerCount , defenderCount ;
2012-09-20 19:55:21 +03:00
bool shooting ;
int chargedFields ;
bool luckyHit ;
2013-05-04 16:14:23 +03:00
bool unluckyHit ;
2012-09-20 19:55:21 +03:00
bool deathBlow ;
bool ballistaDoubleDamage ;
BattleAttackInfo ( const CStack * Attacker , const CStack * Defender , bool Shooting = false ) ;
BattleAttackInfo reverse ( ) const ;
} ;
2012-08-26 12:07:48 +03:00
class DLL_LINKAGE CBattleInfoCallback : public virtual CBattleInfoEssentials
{
public :
enum ERandomSpell
{
RANDOM_GENIE , RANDOM_AIMED
} ;
//battle
2013-09-29 23:54:29 +03:00
boost : : optional < int > battleIsFinished ( ) const ; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
2015-12-29 04:43:33 +02:00
std : : shared_ptr < const CObstacleInstance > battleGetObstacleOnPos ( BattleHex tile , bool onlyBlocking = true ) const ; //blocking obstacles makes tile inaccessible, others cause special effects (like Land Mines, Moat, Quicksands)
2012-08-26 12:07:48 +03:00
const CStack * battleGetStackByPos ( BattleHex pos , bool onlyAlive = true ) const ; //returns stack info by given pos
void battleGetStackQueue ( std : : vector < const CStack * > & out , const int howMany , const int turn = 0 , int lastMoved = - 1 ) const ;
void battleGetStackCountOutsideHexes ( bool * ac ) const ; // returns hexes which when in front of a stack cause us to move the amount box back
2012-08-26 22:13:57 +03:00
2013-06-26 14:18:27 +03:00
std : : vector < BattleHex > battleGetAvailableHexes ( const CStack * stack , bool addOccupiable , std : : vector < BattleHex > * attackable = nullptr ) const ; //returns hexes reachable by creature with id ID (valid movement destinations), DOES contain stack current position
2012-08-26 12:07:48 +03:00
2013-03-03 20:06:03 +03:00
int battleGetSurrenderCost ( PlayerColor Player ) const ; //returns cost of surrendering battle, -1 if surrendering is not possible
2013-06-26 14:18:27 +03:00
ReachabilityInfo : : TDistances battleGetDistances ( const CStack * stack , BattleHex hex = BattleHex : : INVALID , BattleHex * predecessors = nullptr ) const ; //returns vector of distances to [dest hex number]
2012-08-26 12:07:48 +03:00
std : : set < BattleHex > battleGetAttackedHexes ( const CStack * attacker , BattleHex destinationTile , BattleHex attackerPos = BattleHex : : INVALID ) const ;
2016-02-28 04:10:20 +02:00
2015-04-09 21:49:11 +02:00
bool battleCanAttack ( const CStack * stack , const CStack * target , BattleHex dest ) const ; //determines if stack with given ID can attack target at the selected destination
2012-08-26 12:07:48 +03:00
bool battleCanShoot ( const CStack * stack , BattleHex dest ) const ; //determines if stack with given ID shoot at the selected destination
bool battleIsStackBlocked ( const CStack * stack ) const ; //returns true if there is neighboring enemy stack
std : : set < const CStack * > batteAdjacentCreatures ( const CStack * stack ) const ;
2016-02-28 04:10:20 +02:00
2012-09-20 19:55:21 +03:00
TDmgRange calculateDmgRange ( const BattleAttackInfo & info ) const ; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
2013-05-04 16:14:23 +03:00
TDmgRange calculateDmgRange ( const CStack * attacker , const CStack * defender , TQuantity attackerCount , bool shooting , ui8 charge , bool lucky , bool unlucky , bool deathBlow , bool ballistaDoubleDmg ) const ; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
TDmgRange calculateDmgRange ( const CStack * attacker , const CStack * defender , bool shooting , ui8 charge , bool lucky , bool unlucky , bool deathBlow , bool ballistaDoubleDmg ) const ; //charge - number of hexes travelled before attack (for champion's jousting); returns pair <min dmg, max dmg>
2012-08-26 12:07:48 +03:00
//hextowallpart //int battleGetWallUnderHex(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
2016-09-09 19:30:36 +02:00
std : : pair < ui32 , ui32 > battleEstimateDamage ( CRandomGenerator & rand , const BattleAttackInfo & bai , std : : pair < ui32 , ui32 > * retaliationDmg = nullptr ) const ; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
std : : pair < ui32 , ui32 > battleEstimateDamage ( CRandomGenerator & rand , const CStack * attacker , const CStack * defender , std : : pair < ui32 , ui32 > * retaliationDmg = nullptr ) const ; //estimates damage dealt by attacker to defender; it may be not precise especially when stack has randomly working bonuses; returns pair <min dmg, max dmg>
2012-08-26 12:07:48 +03:00
si8 battleHasDistancePenalty ( const CStack * stack , BattleHex destHex ) const ;
2012-09-20 19:55:21 +03:00
si8 battleHasDistancePenalty ( const IBonusBearer * bonusBearer , BattleHex shooterPosition , BattleHex destHex ) const ;
2012-08-26 12:07:48 +03:00
si8 battleHasWallPenalty ( const CStack * stack , BattleHex destHex ) const ; //checks if given stack has wall penalty
2012-09-20 19:55:21 +03:00
si8 battleHasWallPenalty ( const IBonusBearer * bonusBearer , BattleHex shooterPosition , BattleHex destHex ) const ; //checks if given stack has wall penalty
2013-08-06 14:20:28 +03:00
2013-12-08 20:54:13 +03:00
BattleHex wallPartToBattleHex ( EWallPart : : EWallPart part ) const ;
EWallPart : : EWallPart battleHexToWallPart ( BattleHex hex ) const ; //returns part of destructible wall / gate / keep under given hex or -1 if not found
bool isWallPartPotentiallyAttackable ( EWallPart : : EWallPart wallPart ) const ; // returns true if the wall part is potentially attackable (independent of wall state), false if not
std : : vector < BattleHex > getAttackableBattleHexes ( ) const ;
2012-08-26 12:07:48 +03:00
2016-02-28 04:10:20 +02:00
//*** MAGIC
2015-09-16 17:28:14 +02:00
si8 battleMaxSpellLevel ( ui8 side ) const ; //calculates minimum spell level possible to be cast on battlefield - takes into account artifacts of both heroes; if no effects are set, 0 is returned
2012-08-26 12:07:48 +03:00
ui32 battleGetSpellCost ( const CSpell * sp , const CGHeroInstance * caster ) const ; //returns cost of given spell
2016-09-18 17:12:07 +02:00
ESpellCastProblem : : ESpellCastProblem battleCanCastSpell ( const ISpellCaster * caster , ECastingMode : : ECastingMode mode ) const ; //returns true if there are no general issues preventing from casting a spell
2012-08-26 12:07:48 +03:00
2016-09-09 19:30:36 +02:00
SpellID battleGetRandomStackSpell ( CRandomGenerator & rand , const CStack * stack , ERandomSpell mode ) const ;
SpellID getRandomBeneficialSpell ( CRandomGenerator & rand , const CStack * subject ) const ;
SpellID getRandomCastedSpell ( CRandomGenerator & rand , const CStack * caster ) const ; //called at the beginning of turn for Faerie Dragon
2012-08-26 12:07:48 +03:00
2013-06-26 14:18:27 +03:00
const CStack * getStackIf ( std : : function < bool ( const CStack * ) > pred ) const ;
2012-08-26 12:07:48 +03:00
si8 battleHasShootingPenalty ( const CStack * stack , BattleHex destHex )
{
return battleHasDistancePenalty ( stack , destHex ) | | battleHasWallPenalty ( stack , destHex ) ;
}
si8 battleCanTeleportTo ( const CStack * stack , BattleHex destHex , int telportLevel ) const ; //checks if teleportation of given stack to given position can take place
//convenience methods using the ones above
bool isInTacticRange ( BattleHex dest ) const ;
si8 battleGetTacticDist ( ) const ; //returns tactic distance for calling player or 0 if this player is not in tactic phase (for ALL_KNOWING actual distance for tactic side)
2012-11-29 18:02:55 +03:00
AttackableTiles getPotentiallyAttackableHexes ( const CStack * attacker , BattleHex destinationTile , BattleHex attackerPos ) const ; //TODO: apply rotation to two-hex attacker
2012-08-26 12:07:48 +03:00
std : : set < const CStack * > getAttackedCreatures ( const CStack * attacker , BattleHex destinationTile , BattleHex attackerPos = BattleHex : : INVALID ) const ; //calculates range of multi-hex attacks
2012-11-29 18:02:55 +03:00
bool isToReverse ( BattleHex hexFrom , BattleHex hexTo , bool curDir /*if true, creature is in attacker's direction*/ , bool toDoubleWide , bool toDir ) const ; //determines if creature should be reversed (it stands on hexFrom and should 'see' hexTo)
bool isToReverseHlp ( BattleHex hexFrom , BattleHex hexTo , bool curDir ) const ; //helper for isToReverse
2012-08-26 12:07:48 +03:00
ReachabilityInfo getReachability ( const CStack * stack ) const ;
ReachabilityInfo getReachability ( const ReachabilityInfo : : Parameters & params ) const ;
AccessibilityInfo getAccesibility ( ) const ;
2012-08-28 15:28:13 +03:00
AccessibilityInfo getAccesibility ( const CStack * stack ) const ; //Hexes ocupied by stack will be marked as accessible.
AccessibilityInfo getAccesibility ( const std : : vector < BattleHex > & accessibleHexes ) const ; //given hexes will be marked as accessible
2013-05-25 10:06:00 +03:00
std : : pair < const CStack * , BattleHex > getNearestStack ( const CStack * closest , boost : : logic : : tribool attackerOwned ) const ;
2012-08-26 12:07:48 +03:00
protected :
2013-11-07 15:48:41 +03:00
ReachabilityInfo getFlyingReachability ( const ReachabilityInfo : : Parameters & params ) const ;
ReachabilityInfo makeBFS ( const AccessibilityInfo & accessibility , const ReachabilityInfo : : Parameters & params ) const ;
2012-08-26 12:07:48 +03:00
ReachabilityInfo makeBFS ( const CStack * stack ) const ; //uses default parameters -> stack position and owner's perspective
std : : set < BattleHex > getStoppers ( BattlePerspective : : BattlePerspective whichSidePerspective ) const ; //get hexes with stopping obstacles (quicksands)
} ;
class DLL_LINKAGE CPlayerBattleCallback : public CBattleInfoCallback
{
public :
bool battleCanFlee ( ) const ; //returns true if caller can flee from the battle
TStacks battleGetStacks ( EStackOwnership whose = MINE_AND_ENEMY , bool onlyAlive = true ) const ; //returns stacks on battlefield
2015-09-28 15:06:26 +02:00
2012-08-26 12:07:48 +03:00
int battleGetSurrenderCost ( ) const ; //returns cost of surrendering battle, -1 if surrendering is not possible
2012-09-24 02:10:56 +03:00
const CGHeroInstance * battleGetMyHero ( ) const ;
InfoAboutHero battleGetEnemyHero ( ) const ;
2012-08-26 12:07:48 +03:00
} ;