2010-12-25 21:23:30 +02:00
# pragma once
2011-12-14 00:23:17 +03:00
2011-12-22 16:05:19 +03:00
# include "BattleHex.h"
2010-12-25 21:23:30 +02:00
# include "HeroBonus.h"
# include "CCreatureSet.h"
2011-02-06 19:26:27 +02:00
# include "CObjectHandler.h"
# include "CCreatureHandler.h"
2011-05-10 01:20:47 +03:00
# include "CObstacleInstance.h"
2010-12-25 21:23:30 +02:00
# include "ConstTransitivePtr.h"
2011-12-14 00:23:17 +03:00
# include "GameConstants.h"
2012-08-26 12:07:48 +03:00
# include "CBattleCallback.h"
2010-12-25 21:23:30 +02:00
/*
* BattleState . 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
*
*/
class CGHeroInstance ;
class CStack ;
class CArmedInstance ;
class CGTownInstance ;
class CStackInstance ;
2011-01-08 20:33:40 +02:00
struct BattleStackAttacked ;
2010-12-25 21:23:30 +02:00
2011-12-14 00:23:17 +03:00
2012-08-26 12:07:48 +03:00
2010-12-25 21:23:30 +02:00
//only for use in BattleInfo
2011-12-14 00:23:17 +03:00
struct DLL_LINKAGE SiegeInfo
2010-12-25 21:23:30 +02:00
{
2012-08-26 12:07:48 +03:00
ui8 wallState [ EWallParts : : PARTS_COUNT ] ;
2011-12-14 00:23:17 +03:00
2010-12-25 21:23:30 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
h & wallState ;
}
} ;
2011-09-10 16:04:20 +03:00
2012-08-26 12:07:48 +03:00
struct DLL_LINKAGE BattleInfo : public CBonusSystemNode , public CBattleInfoCallback
2010-12-25 21:23:30 +02:00
{
2011-01-09 19:41:46 +02:00
ui8 sides [ 2 ] ; //sides[0] - attacker, sides[1] - defender
2012-04-28 22:40:27 +03:00
si32 round , activeStack , selectedStack ;
2010-12-25 21:23:30 +02:00
ui8 siege ; // = 0 ordinary battle = 1 a siege with a Fort = 2 a siege with a Citadel = 3 a siege with a Castle
2011-01-07 12:48:31 +02:00
const CGTownInstance * town ; //used during town siege - id of attacked town; -1 if not town defence
2010-12-25 21:23:30 +02:00
int3 tile ; //for background and bonuses
2011-12-14 00:23:17 +03:00
CGHeroInstance * heroes [ 2 ] ;
2010-12-25 21:23:30 +02:00
CArmedInstance * belligerents [ 2 ] ; //may be same as heroes
std : : vector < CStack * > stacks ;
2012-05-18 23:50:16 +03:00
std : : vector < shared_ptr < CObstacleInstance > > obstacles ;
2011-02-11 21:12:08 +02:00
ui8 castSpells [ 2 ] ; //how many spells each side has cast this turn [0] - attacker, [1] - defender
2011-10-09 10:20:23 +03:00
std : : vector < const CSpell * > usedSpellsHistory [ 2 ] ; //each time hero casts spell, it's inserted here -> eagle eye skill
si16 enchanterCounter [ 2 ] ; //tends to pass through 0, so sign is needed
2010-12-25 21:23:30 +02:00
SiegeInfo si ;
2012-05-18 23:50:16 +03:00
si32 battlefieldType ; //like !!BA:B
ui8 terrainType ; //used for some stack nativity checks (not the bonus limiters though that have their own copy)
2010-12-25 21:23:30 +02:00
2011-02-12 18:12:48 +02:00
ui8 tacticsSide ; //which side is requested to play tactics phase
ui8 tacticDistance ; //how many hexes we can go forward (1 = only hexes adjacent to margin line)
2010-12-25 21:23:30 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
2012-04-28 22:40:27 +03:00
h & sides & round & activeStack & selectedStack & siege & town & tile & stacks & belligerents & obstacles
2012-05-18 23:50:16 +03:00
& castSpells & si & battlefieldType & terrainType ;
2010-12-25 21:23:30 +02:00
h & heroes ;
2011-10-09 10:20:23 +03:00
h & usedSpellsHistory & enchanterCounter ;
2011-02-12 18:12:48 +02:00
h & tacticsSide & tacticDistance ;
2010-12-25 21:23:30 +02:00
h & static_cast < CBonusSystemNode & > ( * this ) ;
}
2012-08-26 12:07:48 +03:00
//////////////////////////////////////////////////////////////////////////
BattleInfo ( ) ;
~ BattleInfo ( ) { } ;
2010-12-25 21:23:30 +02:00
//////////////////////////////////////////////////////////////////////////
//void getBonuses(BonusList &out, const CSelector &selector, const CBonusSystemNode *root = NULL) const;
//////////////////////////////////////////////////////////////////////////
2012-08-26 12:07:48 +03:00
CStack * getStackT ( BattleHex tileID , bool onlyAlive = true ) ;
CStack * getStack ( int stackID , bool onlyAlive = true ) ;
2010-12-25 21:23:30 +02:00
const CStack * getNextStack ( ) const ; //which stack will have turn after current one
2012-08-26 12:07:48 +03:00
//void getStackQueue(std::vector<const CStack *> &out, int howMany, int turn = 0, int lastMoved = -1) const; //returns stack in order of their movement action
//void getAccessibilityMap(bool *accessibility, bool twoHex, bool attackerOwned, bool addOccupiable, std::set<BattleHex> & occupyable, bool flying, const CStack* stackToOmmit = NULL) const; //send pointer to at least 187 allocated bytes
//static bool isAccessible(BattleHex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
2012-08-28 15:28:13 +03:00
BattleHex getClosestTile ( bool attackerOwned , BattleHex initialPos , std : : set < BattleHex > & possibilities ) const ; //TODO: vector or set? copying one to another is bad
2011-10-01 22:56:54 +03:00
int getAvaliableHex ( TCreature creID , bool attackerOwned , int initialPos = - 1 ) const ; //find place for summon / clone effects
2012-08-26 12:07:48 +03:00
//void makeBFS(BattleHex start, bool*accessibility, BattleHex *predecessor, int *dists, bool twoHex, bool attackerOwned, bool flying, bool fillPredecessors) const; //*accessibility must be prepared bool[187] array; last two pointers must point to the at least 187-elements int arrays - there is written result
std : : pair < std : : vector < BattleHex > , int > getPath ( BattleHex start , BattleHex dest , const CStack * stack ) ; //returned value: pair<path, length>; length may be different than number of elements in path since flying vreatures jump between distant hexes
//std::vector<BattleHex> getAccessibility(const CStack * stack, bool addOccupiable, std::vector<BattleHex> * attackable = NULL, bool forPassingBy = false) const; //returns vector of accessible tiles (taking into account the creature range)
2011-01-07 12:48:31 +02:00
2012-08-26 12:07:48 +03:00
//bool isObstacleVisibleForSide(const CObstacleInstance &obstacle, ui8 side) const;
2012-05-18 23:50:16 +03:00
shared_ptr < CObstacleInstance > getObstacleOnTile ( BattleHex tile ) const ;
std : : set < BattleHex > getStoppers ( bool whichSidePerspective ) const ;
2010-12-25 21:23:30 +02:00
2011-07-06 20:00:45 +03:00
ui32 calculateDmg ( const CStack * attacker , const CStack * defender , const CGHeroInstance * attackerHero , const CGHeroInstance * defendingHero , bool shooting , ui8 charge , bool lucky , bool deathBlow , bool ballistaDoubleDmg ) ; //charge - number of hexes travelled before attack (for champion's jousting)
2010-12-25 21:23:30 +02:00
void calculateCasualties ( std : : map < ui32 , si32 > * casualties ) const ; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
2012-08-26 12:07:48 +03:00
using CBattleInfoCallback : : getAttackedCreatures ;
std : : set < const CStack * > getAttackedCreatures ( const CSpell * s , int skillLevel , ui8 attackerOwner , BattleHex destinationTile ) ; //calculates stack affected by given spell
//void getPotentiallyAttackableHexes(AttackableTiles &at, const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos); //hexes around target that could be attacked in melee
//std::set<CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID); //calculates range of multi-hex attacks
//std::set<BattleHex> getAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID); //calculates range of multi-hex attacks
2010-12-25 21:23:30 +02:00
static int calculateSpellDuration ( const CSpell * spell , const CGHeroInstance * caster , int usedSpellPower ) ;
2012-02-29 04:31:48 +03:00
CStack * generateNewStack ( const CStackInstance & base , bool attackerOwned , int slot , BattleHex position ) const ; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
CStack * generateNewStack ( const CStackBasicDescriptor & base , bool attackerOwned , int slot , BattleHex position ) const ; //helper for CGameHandler::setupBattle and spells addign new stacks to the battlefield
int getIdForNewStack ( ) const ; //suggest a currently unused ID that'd suitable for generating a new stack
2012-08-26 12:07:48 +03:00
//std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const; //if attackerOwned is indetermnate, returened stack is of any owner; hex is the number of hex we should be looking from; returns (nerarest creature, predecessorHex)
2010-12-25 21:23:30 +02:00
ui32 calculateSpellBonus ( ui32 baseDamage , const CSpell * sp , const CGHeroInstance * caster , const CStack * affectedCreature ) const ;
ui32 calculateSpellDmg ( const CSpell * sp , const CGHeroInstance * caster , const CStack * affectedCreature , int spellSchoolLevel , int usedSpellPower ) const ; //calculates damage inflicted by spell
2012-04-28 22:40:27 +03:00
ui32 calculateHealedHP ( const CGHeroInstance * caster , const CSpell * spell , const CStack * stack , const CStack * sacrificedStack = NULL ) const ;
2011-07-08 16:17:05 +03:00
ui32 calculateHealedHP ( int healedHealth , const CSpell * spell , const CStack * stack ) const ; //for Archangel
2011-07-10 01:42:39 +03:00
ui32 calculateHealedHP ( const CSpell * spell , int usedSpellPower , int spellSchoolLevel , const CStack * stack ) const ; //unused
2011-07-08 16:17:05 +03:00
bool resurrects ( TSpell spellid ) const ; //TODO: move it to spellHandler?
2012-08-26 12:07:48 +03:00
2011-02-21 18:53:23 +02:00
const CGHeroInstance * getHero ( int player ) const ; //returns fighting hero that belongs to given player
2011-01-07 12:48:31 +02:00
2011-02-20 20:32:39 +02:00
2012-08-26 12:07:48 +03:00
std : : vector < ui32 > calculateResistedStacks ( const CSpell * sp , const CGHeroInstance * caster , const CGHeroInstance * hero2 , const std : : set < const CStack * > affectedCreatures , int casterSideOwner , ECastingMode : : ECastingMode mode , int usedSpellPower , int spellLevel ) const ;
2011-02-15 21:54:55 +02:00
2011-12-22 16:05:19 +03:00
const CStack * battleGetStack ( BattleHex pos , bool onlyAlive ) ; //returns stack at given tile
2011-01-08 20:33:40 +02:00
const CGHeroInstance * battleGetOwner ( const CStack * stack ) const ; //returns hero that owns given stack; NULL if none
2010-12-25 21:23:30 +02:00
void localInit ( ) ;
2012-02-29 04:31:48 +03:00
void localInitStack ( CStack * s ) ;
2012-05-18 23:50:16 +03:00
static BattleInfo * setupBattle ( int3 tile , int terrain , int battlefieldType , const CArmedInstance * armies [ 2 ] , const CGHeroInstance * heroes [ 2 ] , bool creatureBank , const CGTownInstance * town ) ;
2012-08-26 12:07:48 +03:00
//bool hasNativeStack(ui8 side) const;
2011-03-05 18:38:22 +02:00
int theOtherPlayer ( int player ) const ;
ui8 whatSide ( int player ) const ;
2012-04-23 22:56:37 +03:00
static int battlefieldTypeToBI ( int bfieldType ) ; //converts above to ERM BI format
static int battlefieldTypeToTerrain ( int bfieldType ) ; //converts above to ERM BI format
2010-12-25 21:23:30 +02:00
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CStack : public CBonusSystemNode , public CStackBasicDescriptor
2010-12-25 21:23:30 +02:00
{
public :
2012-08-26 12:07:48 +03:00
const CStackInstance * base ; //garrison slot from which stack originates (NULL for war machines, summoned cres, etc)
2010-12-25 21:23:30 +02:00
ui32 ID ; //unique ID of stack
ui32 baseAmount ;
ui32 firstHPleft ; //HP of first creature in stack
ui8 owner , slot ; //owner - player colour (255 for neutrals), slot - position in garrison (may be 255 for neutrals/called creatures)
ui8 attackerOwned ; //if true, this stack is owned by attakcer (this one from left hand side of battle)
2011-12-22 16:05:19 +03:00
BattleHex position ; //position on battlefield; -2 - keep, -3 - lower tower, -4 - upper tower
2010-12-25 21:23:30 +02:00
ui8 counterAttacks ; //how many counter attacks can be performed more in this turn (by default set at the beginning of the round to 1)
si16 shots ; //how many shots left
2011-07-08 17:54:20 +03:00
ui8 casts ; //how many casts left
2010-12-25 21:23:30 +02:00
2011-12-14 00:23:17 +03:00
std : : set < EBattleStackState : : EBattleStackState > state ;
2010-12-25 21:23:30 +02:00
//overrides
const CCreature * getCreature ( ) const { return type ; }
CStack ( const CStackInstance * base , int O , int I , bool AO , int S ) ; //c-tor
CStack ( const CStackBasicDescriptor * stack , int O , int I , bool AO , int S = 255 ) ; //c-tor
CStack ( ) ; //c-tor
~ CStack ( ) ;
std : : string nodeName ( ) const OVERRIDE ;
void init ( ) ; //set initial (invalid) values
void postInit ( ) ; //used to finish initialization when inheriting creature parameters is working
2011-10-22 10:05:57 +03:00
std : : string getName ( ) const ; //plural or singular
2010-12-25 21:23:30 +02:00
const Bonus * getEffect ( ui16 id , int turn = 0 ) const ; //effect id (SP)
ui8 howManyEffectsSet ( ui16 id ) const ; //returns amount of effects with given id set for this stack
bool willMove ( int turn = 0 ) const ; //if stack has remaining move this turn
2011-09-01 04:40:46 +03:00
bool ableToRetaliate ( ) const ; //if stack can retaliate after attacked
2010-12-25 21:23:30 +02:00
bool moved ( int turn = 0 ) const ; //if stack was already moved this turn
bool canMove ( int turn = 0 ) const ; //if stack can move
2012-03-31 00:36:07 +03:00
bool canBeHealed ( ) const ; //for first aid tent - only harmed stacks that are not war machines
2011-10-17 11:24:51 +03:00
ui32 Speed ( int turn = 0 , bool useBind = false ) const ; //get speed of creature with all modificators
2011-10-20 14:03:04 +03:00
si32 magicResistance ( ) const ; //include aura of resistance
2011-01-20 21:57:12 +02:00
static void stackEffectToFeature ( std : : vector < Bonus > & sf , const Bonus & sse ) ;
2010-12-25 21:23:30 +02:00
std : : vector < si32 > activeSpells ( ) const ; //returns vector of active spell IDs sorted by time of cast
const CGHeroInstance * getMyHero ( ) const ; //if stack belongs to hero (directly or was by him summoned) returns hero, NULL otherwise
2011-01-20 21:57:12 +02:00
static inline Bonus featureGenerator ( Bonus : : BonusType type , si16 subtype , si32 value , ui16 turnsRemain , si32 additionalInfo = 0 , si32 limit = Bonus : : NO_LIMIT )
2010-12-25 21:23:30 +02:00
{
2011-01-20 21:57:12 +02:00
Bonus hb = makeFeatureVal ( type , Bonus : : N_TURNS , subtype , value , Bonus : : SPELL_EFFECT , turnsRemain , additionalInfo ) ;
hb . effectRange = limit ;
hb . source = Bonus : : SPELL_EFFECT ;
2010-12-25 21:23:30 +02:00
return hb ;
}
2011-01-20 21:57:12 +02:00
static inline Bonus featureGeneratorVT ( Bonus : : BonusType type , si16 subtype , si32 value , ui16 turnsRemain , ui8 valType )
2010-12-25 21:23:30 +02:00
{
2011-01-20 21:57:12 +02:00
Bonus ret = makeFeatureVal ( type , Bonus : : N_TURNS , subtype , value , Bonus : : SPELL_EFFECT , turnsRemain ) ;
ret . valType = valType ;
ret . source = Bonus : : SPELL_EFFECT ;
2010-12-25 21:23:30 +02:00
return ret ;
}
2011-12-22 16:05:19 +03:00
static bool isMeleeAttackPossible ( const CStack * attacker , const CStack * defender , BattleHex attackerPos = BattleHex : : INVALID , BattleHex defenderPos = BattleHex : : INVALID ) ;
2011-01-08 20:33:40 +02:00
2010-12-25 21:23:30 +02:00
bool doubleWide ( ) const ;
2011-12-22 16:05:19 +03:00
BattleHex occupiedHex ( ) const ; //returns number of occupied hex (not the position) if stack is double wide; otherwise -1
2012-08-26 12:07:48 +03:00
BattleHex occupiedHex ( BattleHex assumedPos ) const ; //returns number of occupied hex (not the position) if stack is double wide and would stand on assumedPos; otherwise -1
2011-12-22 16:05:19 +03:00
std : : vector < BattleHex > getHexes ( ) const ; //up to two occupied hexes, starting from front
2012-08-26 12:07:48 +03:00
std : : vector < BattleHex > getHexes ( BattleHex assumedPos ) const ; //up to two occupied hexes, starting from front
static std : : vector < BattleHex > getHexes ( BattleHex assumedPos , bool twoHex , bool AttackerOwned ) ; //up to two occupied hexes, starting from front
2011-12-22 16:05:19 +03:00
bool coversPos ( BattleHex position ) const ; //checks also if unit is double-wide
std : : vector < BattleHex > getSurroundingHexes ( BattleHex attackerPos = BattleHex : : INVALID ) const ; // get six or 8 surrounding hexes depending on creature size
2010-12-25 21:23:30 +02:00
2011-01-08 20:33:40 +02:00
void prepareAttacked ( BattleStackAttacked & bsa ) const ; //requires bsa.damageAmout filled
2010-12-25 21:23:30 +02:00
template < typename Handler > void serialize ( Handler & h , const int version )
{
assert ( isIndependentNode ( ) ) ;
h & static_cast < CBonusSystemNode & > ( * this ) ;
h & static_cast < CStackBasicDescriptor & > ( * this ) ;
h & ID & baseAmount & firstHPleft & owner & slot & attackerOwned & position & state & counterAttacks
2011-07-08 17:54:20 +03:00
& shots & casts & count ;
2010-12-25 21:23:30 +02:00
const CArmedInstance * army = ( base ? base - > armyObj : NULL ) ;
2012-08-20 19:10:50 +03:00
TSlot slot = ( base ? base - > armyObj - > findStack ( base ) : - 1 ) ;
2010-12-25 21:23:30 +02:00
if ( h . saving )
{
h & army & slot ;
}
else
{
h & army & slot ;
2012-08-20 19:10:50 +03:00
if ( slot = = - 2 ) //TODO
{
auto hero = dynamic_cast < const CGHeroInstance * > ( army ) ;
assert ( hero ) ;
base = hero - > commander ;
}
else if ( ! army | | slot = = - 1 | | ! army - > hasStackAtSlot ( slot ) )
2010-12-25 21:23:30 +02:00
{
base = NULL ;
2011-06-19 02:56:48 +03:00
tlog3 < < type - > nameSing < < " doesn't have a base stack! \n " ;
2010-12-25 21:23:30 +02:00
}
else
{
base = & army - > getStack ( slot ) ;
}
}
}
bool alive ( ) const //determines if stack is alive
{
2011-12-14 00:23:17 +03:00
return vstd : : contains ( state , EBattleStackState : : ALIVE ) ;
2010-12-25 21:23:30 +02:00
}
2012-02-17 00:19:07 +03:00
bool isValidTarget ( bool allowDead = false ) const ; //alive non-turret stacks (can be attacked or be object of magic effect)
2010-12-25 21:23:30 +02:00
} ;
2011-12-14 00:23:17 +03:00
class DLL_LINKAGE CMP_stack
2010-12-25 21:23:30 +02:00
{
int phase ; //rules of which phase will be used
int turn ;
public :
bool operator ( ) ( const CStack * a , const CStack * b ) ;
CMP_stack ( int Phase = 1 , int Turn = 0 ) ;
} ;