1
0
mirror of https://github.com/vcmi/vcmi.git synced 2024-11-24 08:32:34 +02:00

Merge pull request #316 from FeniksFire/improvingTheBattle

Refactoring.
This commit is contained in:
ArseniyShestakov 2017-06-28 19:55:03 +03:00 committed by GitHub
commit bd27636cd9
62 changed files with 1363 additions and 1161 deletions

View File

@ -9,7 +9,7 @@
*/
#pragma once
#include "../../lib/BattleHex.h"
#include "../../lib/battle/BattleHex.h"
class CStack;

View File

@ -1,6 +1,6 @@
#pragma once
#include "../../lib/BattleHex.h"
#include "../../lib/battle/BattleHex.h"
class CStupidAI : public CBattleGameInterface
{

View File

@ -18,7 +18,7 @@
#include "lib/GameConstants.h"
#include "lib/CPlayerState.h"
#include "lib/UnlockGuard.h"
#include "lib/BattleInfo.h"
#include "lib/battle/BattleInfo.h"
/*
* CCallback.cpp, part of VCMI engine

View File

@ -11,7 +11,7 @@
#include "../lib/CGameState.h"
#include "CPlayerInterface.h"
#include "../lib/StartInfo.h"
#include "../lib/BattleInfo.h"
#include "../lib/battle/BattleInfo.h"
#include "../lib/CModHandler.h"
#include "../lib/CArtHandler.h"
#include "../lib/CGeneralTextHandler.h"

View File

@ -2,7 +2,7 @@
#include "../lib/IGameCallback.h"
#include "../lib/BattleAction.h"
#include "../lib/battle/BattleAction.h"
#include "../lib/CStopWatch.h"
#include "../lib/int3.h"

View File

@ -25,7 +25,7 @@
#include "../lib/mapping/CCampaignHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CStack.h"
#include "../lib/BattleInfo.h"
#include "../lib/battle/BattleInfo.h"
#include "../lib/GameConstants.h"
#include "../lib/CPlayerState.h"
#include "gui/CGuiHandler.h"

View File

@ -944,7 +944,7 @@ bool CSpellEffectAnimation::init()
{
const CStack* destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(destTile, false);
Rect &tilePos = owner->bfield[destTile]->pos;
Rect & tilePos = owner->bfield[destTile]->pos;
BattleEffect be;
be.effectID = ID;
be.anim = CDefHandler::giveDef(customAnim);

View File

@ -1,6 +1,6 @@
#pragma once
#include "../../lib/BattleHex.h"
#include "../../lib/battle/BattleHex.h"
#include "../widgets/Images.h"
class CBattleInterface;

View File

@ -1,7 +1,7 @@
#pragma once
#include "../gui/CIntObject.h"
#include "../../lib/BattleHex.h"
#include "../../lib/battle/BattleHex.h"
#include "../windows/CWindowObject.h"
struct SDL_Surface;

View File

@ -1,341 +0,0 @@
#pragma once
#include "BattleHex.h"
/*
* 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
*
*/
class CGameState;
class CGTownInstance;
class CGHeroInstance;
class CStack;
class ISpellCaster;
class CSpell;
struct BattleInfo;
struct CObstacleInstance;
class IBonusBearer;
struct InfoAboutHero;
class CArmedInstance;
class CRandomGenerator;
namespace boost
{class shared_mutex;}
namespace BattleSide
{
enum {ATTACKER = 0, DEFENDER = 1};
}
typedef std::vector<const CStack*> TStacks;
typedef std::function<bool(const CStack *)> TStackFilter;
class CBattleInfoEssentials;
//Basic class for various callbacks (interfaces called by players to get info about game and so forth)
class DLL_LINKAGE CCallbackBase
{
const BattleInfo *battle; //battle to which the player is engaged, nullptr if none or not applicable
const BattleInfo * getBattle() const
{
return battle;
}
protected:
CGameState *gs;
boost::optional<PlayerColor> player; // not set gives access to all information, otherwise callback provides only information "visible" for player
CCallbackBase(CGameState *GS, boost::optional<PlayerColor> Player)
: battle(nullptr), gs(GS), player(Player)
{}
CCallbackBase()
: battle(nullptr), gs(nullptr)
{}
void setBattle(const BattleInfo *B);
bool duringBattle() const;
public:
boost::optional<PlayerColor> getPlayerID() const;
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
{
ACCESSIBLE,
ALIVE_STACK,
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
};
}
// Reachability info is result of BFS calculation. It's dependent on stack (it's owner, whether it's flying),
// startPosition and perpective.
struct DLL_LINKAGE ReachabilityInfo
{
typedef std::array<int, GameConstants::BFIELD_SIZE> TDistances;
typedef std::array<BattleHex, GameConstants::BFIELD_SIZE> TPredecessors;
enum { INFINITE_DIST = 1000000 };
struct DLL_LINKAGE Parameters
{
const CStack *stack; //stack for which calculation is mage => not required (kept for debugging mostly), following variables are enough
bool attackerOwned;
bool doubleWide;
bool flying;
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)
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()
{
distances.fill(INFINITE_DIST);
predecessors.fill(BattleHex::INVALID);
}
bool isReachable(BattleHex hex) const
{
return distances[hex] < INFINITE_DIST;
}
};
class DLL_LINKAGE CBattleInfoEssentials : public virtual CCallbackBase
{
protected:
bool battleDoWeKnowAbout(ui8 side) const;
const IBonusBearer * getBattleNode() const;
public:
enum EStackOwnership
{
ONLY_MINE, ONLY_ENEMY, MINE_AND_ENEMY
};
BattlePerspective::BattlePerspective battleGetMySide() const;
ETerrainType battleTerrainType() const;
BFieldType battleGetBattlefieldType() const;
std::vector<std::shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
/** @brief Main method for getting battle stacks
*
* @param predicate Functor that shall return true for desired stack
* @return filtered stacks
*
*/
TStacks battleGetStacksIf(TStackFilter predicate) const;
bool battleHasNativeStack(ui8 side) const;
int battleGetMoatDmg() const; //what dmg unit will suffer if ending turn in the moat
const CGTownInstance * battleGetDefendedTown() const; //returns defended town if current battle is a siege, nullptr instead
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 (?)
bool battleCanFlee(PlayerColor player) const;
bool battleCanSurrender(PlayerColor player) const;
si8 playerToSide(PlayerColor player) const;
bool playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const;
ui8 battleGetSiegeLevel() const; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
bool battleHasHero(ui8 side) const;
int battleCastSpells(ui8 side) const; //how many spells has given side cast
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //depracated for players callback, easy to get wrong
const CArmedInstance * battleGetArmyObject(ui8 side) const;
InfoAboutHero battleGetHeroInfo(ui8 side) const;
// 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;
EGateState battleGetGateState() const;
//helpers
///returns all stacks, alive or dead or undead or mechanical :)
TStacks battleGetAllStacks(bool includeTurrets = false) const;
///returns all alive stacks excluding turrets
TStacks battleAliveStacks() const;
///returns all alive stacks from particular side excluding turrets
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;
///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;
};
struct DLL_LINKAGE BattleAttackInfo
{
const IBonusBearer *attackerBonuses, *defenderBonuses;
const CStack *attacker, *defender;
BattleHex attackerPosition, defenderPosition;
int attackerCount, defenderCount;
bool shooting;
int chargedFields;
bool luckyHit;
bool unluckyHit;
bool deathBlow;
bool ballistaDoubleDamage;
BattleAttackInfo(const CStack *Attacker, const CStack *Defender, bool Shooting = false);
BattleAttackInfo reverse() const;
};
class DLL_LINKAGE CBattleInfoCallback : public virtual CBattleInfoEssentials
{
public:
enum ERandomSpell
{
RANDOM_GENIE, RANDOM_AIMED
};
//battle
boost::optional<int> battleIsFinished() const; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
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)
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
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
int battleGetSurrenderCost(PlayerColor Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible
ReachabilityInfo::TDistances battleGetDistances(const CStack * stack, BattleHex hex = BattleHex::INVALID, BattleHex * predecessors = nullptr) const; //returns vector of distances to [dest hex number]
std::set<BattleHex> battleGetAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const;
bool battleCanAttack(const CStack * stack, const CStack * target, BattleHex dest) const; //determines if stack with given ID can attack target at the selected destination
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;
TDmgRange calculateDmgRange(const BattleAttackInfo &info) 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, 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>
//hextowallpart //int battleGetWallUnderHex(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
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>
si8 battleHasDistancePenalty( const CStack * stack, BattleHex destHex ) const;
si8 battleHasDistancePenalty(const IBonusBearer *bonusBearer, BattleHex shooterPosition, BattleHex destHex ) const;
si8 battleHasWallPenalty(const CStack * stack, BattleHex destHex) const; //checks if given stack has wall penalty
si8 battleHasWallPenalty(const IBonusBearer *bonusBearer, BattleHex shooterPosition, BattleHex destHex) const; //checks if given stack has wall penalty
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;
//*** MAGIC
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
ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
ESpellCastProblem::ESpellCastProblem battleCanCastSpell(const ISpellCaster * caster, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell
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
const CStack * getStackIf(std::function<bool(const CStack*)> pred) const;
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)
AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const; //TODO: apply rotation to two-hex attacker
std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
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
ReachabilityInfo getReachability(const CStack *stack) const;
ReachabilityInfo getReachability(const ReachabilityInfo::Parameters &params) const;
AccessibilityInfo getAccesibility() const;
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
std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const;
protected:
ReachabilityInfo getFlyingReachability(const ReachabilityInfo::Parameters &params) const;
ReachabilityInfo makeBFS(const AccessibilityInfo &accessibility, const ReachabilityInfo::Parameters &params) const;
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
int battleGetSurrenderCost() const; //returns cost of surrendering battle, -1 if surrendering is not possible
const CGHeroInstance * battleGetMyHero() const;
InfoAboutHero battleGetEnemyHero() const;
};

View File

@ -15,7 +15,7 @@
#include "CGeneralTextHandler.h"
#include "mapObjects/CObjectHandler.h" // for CGObjectInstance
#include "StartInfo.h" // for StartInfo
#include "BattleInfo.h" // for BattleInfo
#include "battle/BattleInfo.h" // for BattleInfo
#include "NetPacks.h" // for InfoWindow
#include "CModHandler.h"
#include "spells/CSpellHandler.h"

View File

@ -1,7 +1,7 @@
#pragma once
#include "ResourceSet.h" // for Res::ERes
#include "CBattleCallback.h" //for CCallbackBase
#include "battle/CPlayerBattleCallback.h"
/*
* CGameInfoCallback.h, part of VCMI engine

View File

@ -1,7 +1,7 @@
#pragma once
#include "BattleAction.h"
#include "battle/BattleAction.h"
#include "IGameEventsReceiver.h"
#include "CGameStateFwd.h"

View File

@ -16,7 +16,7 @@
#include "StartInfo.h"
#include "NetPacks.h"
#include "registerTypes/RegisterTypes.h"
#include "BattleInfo.h"
#include "battle/BattleInfo.h"
#include "JsonNode.h"
#include "filesystem/Filesystem.h"
#include "GameConstants.h"

View File

@ -6,7 +6,7 @@
#include "VCMI_Lib.h"
#include "JsonNode.h"
#include "StringConstants.h"
#include "BattleHex.h"
#include "battle/BattleHex.h"
#include "CCreatureHandler.h"
#include "CModHandler.h"
#include "CTownHandler.h"

View File

@ -76,14 +76,20 @@ set(lib_SRCS
spells/CDefaultSpellMechanics.cpp
spells/ViewSpellInt.cpp
BattleAction.cpp
BattleHex.cpp
BattleInfo.cpp
SiegeInfo.cpp
SideInBattle.cpp
CStack.cpp
battle/BattleAction.cpp
battle/BattleHex.cpp
battle/BattleInfo.cpp
battle/AccessibilityInfo.cpp
battle/BattleAttackInfo.cpp
battle/CBattleInfoCallback.cpp
battle/CBattleInfoEssentials.cpp
battle/CCallbackBase.cpp
battle/CPlayerBattleCallback.cpp
battle/ReachabilityInfo.cpp
SiegeInfo.cpp
SideInBattle.cpp
CStack.cpp
CArtHandler.cpp
CBattleCallback.cpp
CBonusTypeHandler.cpp
CBuildingHandler.cpp
CConfigHandler.cpp
@ -94,7 +100,7 @@ set(lib_SRCS
CGeneralTextHandler.cpp
CHeroHandler.cpp
CModHandler.cpp
CObstacleInstance.cpp
battle/CObstacleInstance.cpp
CRandomGenerator.cpp
CThreadHelper.cpp

View File

@ -9,7 +9,7 @@
*/
#include "StdInc.h"
#include "CStack.h"
#include "BattleInfo.h"
#include "battle/BattleInfo.h"
#include "spells/CSpellHandler.h"
#include "CRandomGenerator.h"
#include "NetPacks.h"

View File

@ -8,7 +8,7 @@
*
*/
#pragma once
#include "BattleHex.h"
#include "battle/BattleHex.h"
#include "CCreatureHandler.h"
#include "mapObjects/CGHeroInstance.h" // for commander serialization

View File

@ -6,7 +6,7 @@
#include "GameConstants.h"
#include "IHandlerBase.h"
#include "LogicalExpression.h"
#include "BattleHex.h"
#include "battle/BattleHex.h"
/*
* CTownHandler.h, part of VCMI engine

View File

@ -10,7 +10,7 @@
#pragma once
#include "BattleHex.h"
#include "battle/BattleHex.h"
#include "int3.h"
class CGTownInstance;

View File

@ -2,14 +2,14 @@
#include "NetPacksBase.h"
#include "BattleAction.h"
#include "battle/BattleAction.h"
#include "mapObjects/CGHeroInstance.h"
#include "ConstTransitivePtr.h"
#include "int3.h"
#include "ResourceSet.h"
#include "CGameStateFwd.h"
#include "mapping/CMapDefines.h"
#include "CObstacleInstance.h"
#include "battle/CObstacleInstance.h"
#include "spells/ViewSpellInt.h"

View File

@ -13,7 +13,7 @@
#include "CCreatureHandler.h"
#include "CGameState.h"
#include "CStack.h"
#include "BattleInfo.h"
#include "battle/BattleInfo.h"
#include "CTownHandler.h"
#include "mapping/CMapInfo.h"
#include "StartInfo.h"

View File

@ -125,16 +125,28 @@
<Unit filename="../Version.h" />
<Unit filename="../include/vstd/CLoggerBase.h" />
<Unit filename="AI_Base.h" />
<Unit filename="BattleAction.cpp" />
<Unit filename="BattleAction.h" />
<Unit filename="BattleHex.cpp" />
<Unit filename="BattleHex.h" />
<Unit filename="BattleInfo.cpp" />
<Unit filename="BattleInfo.h" />
<Unit filename="battle/BattleAction.cpp" />
<Unit filename="battle/BattleAction.h" />
<Unit filename="battle/BattleHex.cpp" />
<Unit filename="battle/BattleHex.h" />
<Unit filename="battle/BattleInfo.cpp" />
<Unit filename="battle/BattleInfo.h" />
<Unit filename="battle/AccessibilityInfo.cpp" />
<Unit filename="battle/AccessibilityInfo.h" />
<Unit filename="battle/BattleAttackInfo.cpp" />
<Unit filename="battle/BattleAttackInfo.h" />
<Unit filename="battle/CBattleInfoCallback.cpp" />
<Unit filename="battle/CBattleInfoCallback.h" />
<Unit filename="battle/CBattleInfoEssentials.cpp" />
<Unit filename="battle/CBattleInfoEssentials.h" />
<Unit filename="battle/CCallbackBase.cpp" />
<Unit filename="battle/CCallbackBase.h" />
<Unit filename="battle/CPlayerBattleCallback.cpp" />
<Unit filename="battle/CPlayerBattleCallback.h" />
<Unit filename="battle/ReachabilityInfo.cpp" />
<Unit filename="battle/ReachabilityInfo.h" />
<Unit filename="CArtHandler.cpp" />
<Unit filename="CArtHandler.h" />
<Unit filename="CBattleCallback.cpp" />
<Unit filename="CBattleCallback.h" />
<Unit filename="CBonusTypeHandler.cpp" />
<Unit filename="CBonusTypeHandler.h" />
<Unit filename="CBuildingHandler.cpp" />
@ -161,8 +173,8 @@
<Unit filename="CMakeLists.txt" />
<Unit filename="CModHandler.cpp" />
<Unit filename="CModHandler.h" />
<Unit filename="CObstacleInstance.cpp" />
<Unit filename="CObstacleInstance.h" />
<Unit filename="battle/CObstacleInstance.cpp" />
<Unit filename="battle/CObstacleInstance.h" />
<Unit filename="CPathfinder.cpp" />
<Unit filename="CPathfinder.h" />
<Unit filename="CPlayerState.h" />

View File

@ -168,9 +168,16 @@
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClCompile Include="BattleAction.cpp" />
<ClCompile Include="BattleHex.cpp" />
<ClCompile Include="BattleInfo.cpp" />
<ClCompile Include="battle\BattleAction.cpp" />
<ClCompile Include="battle\BattleHex.cpp" />
<ClCompile Include="battle\BattleInfo.cpp" />
<ClCompile Include="battle\AccessibilityInfo.cpp" />
<ClCompile Include="battle\BattleAttackInfo.cpp" />
<ClCompile Include="battle\CBattleInfoCallback.cpp" />
<ClCompile Include="battle\CBattleInfoEssentials.cpp" />
<ClCompile Include="battle\CCallbackBase.cpp" />
<ClCompile Include="battle\CPlayerBattleCallback.cpp" />
<ClCompile Include="battle\ReachabilityInfo.cpp" />
<ClCompile Include="CArtHandler.cpp" />
<ClCompile Include="CBonusTypeHandler.cpp" />
<ClCompile Include="CBuildingHandler.cpp" />
@ -183,7 +190,7 @@
<ClCompile Include="CGeneralTextHandler.cpp" />
<ClCompile Include="CHeroHandler.cpp" />
<ClCompile Include="CModHandler.cpp" />
<ClCompile Include="CObstacleInstance.cpp" />
<ClCompile Include="battle\CObstacleInstance.cpp" />
<ClCompile Include="CPathfinder.cpp" />
<ClCompile Include="CStack.cpp" />
<ClCompile Include="CThreadHelper.cpp" />
@ -262,7 +269,6 @@
<ClCompile Include="logging\CLogger.cpp" />
<ClCompile Include="logging\CBasicLogConfigurator.cpp" />
<ClCompile Include="HeroBonus.cpp" />
<ClCompile Include="CBattleCallback.cpp" />
<ClCompile Include="IGameCallback.cpp" />
<ClCompile Include="CGameInfoCallback.cpp" />
<ClCompile Include="JsonNode.cpp" />
@ -290,9 +296,16 @@
<ClInclude Include="..\Global.h" />
<ClInclude Include="..\Version.h" />
<ClInclude Include="AI_Base.h" />
<ClInclude Include="BattleAction.h" />
<ClInclude Include="BattleHex.h" />
<ClInclude Include="BattleInfo.h" />
<ClInclude Include="battle\BattleAction.h" />
<ClInclude Include="battle\BattleHex.h" />
<ClInclude Include="battle\BattleInfo.h" />
<ClInclude Include="battle\AccessibilityInfo.h" />
<ClInclude Include="battle\BattleAttackInfo.h" />
<ClInclude Include="battle\CBattleInfoCallback.h" />
<ClInclude Include="battle\CBattleInfoEssentials.h" />
<ClInclude Include="battle\CCallbackBase.h" />
<ClInclude Include="battle\CPlayerBattleCallback.h" />
<ClInclude Include="battle\ReachabilityInfo.h" />
<ClInclude Include="CArtHandler.h" />
<ClInclude Include="CBonusTypeHandler.h" />
<ClInclude Include="CBuildingHandler.h" />
@ -306,7 +319,7 @@
<ClInclude Include="CGeneralTextHandler.h" />
<ClInclude Include="CHeroHandler.h" />
<ClInclude Include="CModHandler.h" />
<ClInclude Include="CObstacleInstance.h" />
<ClInclude Include="battle\CObstacleInstance.h" />
<ClInclude Include="CondSh.h" />
<ClInclude Include="ConstTransitivePtr.h" />
<ClInclude Include="CPathfinder.h" />
@ -376,7 +389,6 @@
<ClInclude Include="logging\CBasicLogConfigurator.h" />
<ClInclude Include="GameConstants.h" />
<ClInclude Include="HeroBonus.h" />
<ClInclude Include="CBattleCallback.h" />
<ClInclude Include="IGameCallback.h" />
<ClInclude Include="CGameInfoCallback.h" />
<ClInclude Include="IGameEventsReceiver.h" />
@ -425,4 +437,4 @@
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>
</Project>

View File

@ -31,7 +31,7 @@
</Filter>
</ItemGroup>
<ItemGroup>
<ClCompile Include="BattleAction.cpp" />
<ClCompile Include="battle\BattleAction.cpp" />
<ClCompile Include="CArtHandler.cpp" />
<ClCompile Include="CBuildingHandler.cpp" />
<ClCompile Include="CCreatureHandler.cpp" />
@ -49,14 +49,20 @@
<ClCompile Include="ResourceSet.cpp" />
<ClCompile Include="CGameInterface.cpp" />
<ClCompile Include="JsonNode.cpp" />
<ClCompile Include="BattleHex.cpp" />
<ClCompile Include="battle\BattleHex.cpp" />
<ClCompile Include="CConsoleHandler.cpp" />
<ClCompile Include="CThreadHelper.cpp" />
<ClCompile Include="StdInc.cpp" />
<ClCompile Include="CObstacleInstance.cpp" />
<ClCompile Include="battle\CObstacleInstance.cpp" />
<ClCompile Include="CModHandler.cpp" />
<ClCompile Include="CConfigHandler.cpp" />
<ClCompile Include="CBattleCallback.cpp" />
<ClCompile Include="battle\AccessibilityInfo.cpp" />
<ClCompile Include="battle\BattleAttackInfo.cpp" />
<ClCompile Include="battle\CBattleInfoCallback.cpp" />
<ClCompile Include="battle\CBattleInfoEssentials.cpp" />
<ClCompile Include="battle\CCallbackBase.cpp" />
<ClCompile Include="battle\CPlayerBattleCallback.cpp" />
<ClCompile Include="battle\ReachabilityInfo.cpp" />
<ClCompile Include="Mapping\CCampaignHandler.cpp" />
<ClCompile Include="GameConstants.cpp" />
<ClCompile Include="VCMIDirs.cpp" />
@ -263,7 +269,7 @@
<ClCompile Include="CStack.cpp" />
<ClCompile Include="SideInBattle.cpp" />
<ClCompile Include="SiegeInfo.cpp" />
<ClCompile Include="BattleInfo.cpp" />
<ClCompile Include="battle\BattleInfo.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="CCreatureSet.h">
@ -317,10 +323,10 @@
<ClInclude Include="CTownHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BattleAction.h">
<ClInclude Include="battle\BattleAction.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CObstacleInstance.h">
<ClInclude Include="battle\CObstacleInstance.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="IGameEventsReceiver.h">
@ -344,7 +350,7 @@
<ClInclude Include="AI_Base.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BattleHex.h">
<ClInclude Include="battle\BattleHex.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CConsoleHandler.h">
@ -380,7 +386,25 @@
<ClInclude Include="CConfigHandler.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CBattleCallback.h">
<ClInclude Include="AccessibilityInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BattleAttackInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CBattleInfoCallback.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CBattleInfoEssentials.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CCallbackBase.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CPlayerBattleCallback.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ReachabilityInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Mapping\CCampaignHandler.h">
@ -656,7 +680,7 @@
<ClInclude Include="serializer\Connection.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BattleInfo.h">
<ClInclude Include="battle\BattleInfo.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="CStack.h">

View File

@ -0,0 +1,51 @@
/*
* AccessibilityInfo.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
*
*/
#include "StdInc.h"
#include "AccessibilityInfo.h"
#include "CStack.h"
bool AccessibilityInfo::accessible(BattleHex tile, const CStack * stack) const
{
return accessible(tile, stack->doubleWide(), stack->attackerOwned);
}
bool AccessibilityInfo::accessible(BattleHex tile, bool doubleWide, bool attackerOwned) const
{
// All hexes that stack would cover if standing on tile have to be accessible.
for(auto hex : CStack::getHexes(tile, doubleWide, attackerOwned))
{
// If the hex is out of range then the tile isn't accessible
if(!hex.isValid())
return false;
// If we're no defender which step on gate and the hex isn't accessible, then the tile
// isn't accessible
else if(at(hex) != EAccessibility::ACCESSIBLE &&
!(at(hex) == EAccessibility::GATE && !attackerOwned))
{
return false;
}
}
return true;
}
bool AccessibilityInfo::occupiable(const CStack * stack, BattleHex tile) const
{
//obviously, we can occupy tile by standing on it
if(accessible(tile, stack))
return true;
if(stack->doubleWide())
{
//Check the tile next to -> if stack stands there, it'll also occupy considered hex
const BattleHex anotherTile = tile + (stack->attackerOwned ? BattleHex::RIGHT : BattleHex::LEFT);
if(accessible(anotherTile, stack))
return true;
}
return false;
}

View File

@ -0,0 +1,35 @@
/*
* AccessibilityInfo.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
*
*/
#pragma once
#include "BattleHex.h"
class CStack;
//Accessibility is property of hex in battle. It doesn't depend on stack, side's perspective and so on.
enum class EAccessibility
{
ACCESSIBLE,
ALIVE_STACK,
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, 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
};

View File

@ -1,9 +1,3 @@
#include "StdInc.h"
#include "BattleAction.h"
#include "CStack.h"
/*
* BattleAction.cpp, part of VCMI engine
*
@ -14,6 +8,10 @@
*
*/
#include "StdInc.h"
#include "BattleAction.h"
#include "CStack.h"
using namespace Battle;
BattleAction::BattleAction():
@ -26,7 +24,7 @@ BattleAction::BattleAction():
{
}
BattleAction BattleAction::makeHeal(const CStack *healer, const CStack *healed)
BattleAction BattleAction::makeHeal(const CStack * healer, const CStack * healed)
{
BattleAction ba;
ba.side = !healer->attackerOwned;
@ -36,7 +34,7 @@ BattleAction BattleAction::makeHeal(const CStack *healer, const CStack *healed)
return ba;
}
BattleAction BattleAction::makeDefend(const CStack *stack)
BattleAction BattleAction::makeDefend(const CStack * stack)
{
BattleAction ba;
ba.side = !stack->attackerOwned;
@ -46,7 +44,7 @@ BattleAction BattleAction::makeDefend(const CStack *stack)
}
BattleAction BattleAction::makeMeleeAttack(const CStack *stack, const CStack * attacked, BattleHex attackFrom /*= BattleHex::INVALID*/)
BattleAction BattleAction::makeMeleeAttack(const CStack * stack, const CStack * attacked, BattleHex attackFrom /*= BattleHex::INVALID*/)
{
BattleAction ba;
ba.side = !stack->attackerOwned;
@ -57,7 +55,7 @@ BattleAction BattleAction::makeMeleeAttack(const CStack *stack, const CStack * a
return ba;
}
BattleAction BattleAction::makeWait(const CStack *stack)
BattleAction BattleAction::makeWait(const CStack * stack)
{
BattleAction ba;
ba.side = !stack->attackerOwned;
@ -66,7 +64,7 @@ BattleAction BattleAction::makeWait(const CStack *stack)
return ba;
}
BattleAction BattleAction::makeShotAttack(const CStack *shooter, const CStack *target)
BattleAction BattleAction::makeShotAttack(const CStack * shooter, const CStack * target)
{
BattleAction ba;
ba.side = !shooter->attackerOwned;
@ -76,7 +74,7 @@ BattleAction BattleAction::makeShotAttack(const CStack *shooter, const CStack *t
return ba;
}
BattleAction BattleAction::makeMove(const CStack *stack, BattleHex dest)
BattleAction BattleAction::makeMove(const CStack * stack, BattleHex dest)
{
BattleAction ba;
ba.side = !stack->attackerOwned;

View File

@ -1,8 +1,3 @@
#pragma once
#include "BattleHex.h"
/*
* BattleAction.h, part of VCMI engine
*
@ -12,14 +7,16 @@
* Full text of license available in license.txt file, in main folder
*
*/
#pragma once
#include "BattleHex.h"
/// A struct which handles battle actions like defending, walking,... - represents a creature stack in a battle
class CStack;
/// A struct which handles battle actions like defending, walking,... - represents a creature stack in a battle
struct DLL_LINKAGE BattleAction
{
ui8 side; //who made this action: false - left, true - right player
ui32 stackNumber;//stack ID, -1 left hero, -2 right hero,
ui32 stackNumber; //stack ID, -1 left hero, -2 right hero,
Battle::ActionType actionType; //use ActionType enum for values
BattleHex destinationTile;
si32 additionalInfo; // e.g. spell number if type is 1 || 10; tile to attack if type is 6
@ -32,12 +29,12 @@ struct DLL_LINKAGE BattleAction
BattleAction();
static BattleAction makeHeal(const CStack *healer, const CStack *healed);
static BattleAction makeDefend(const CStack *stack);
static BattleAction makeWait(const CStack *stack);
static BattleAction makeMeleeAttack(const CStack *stack, const CStack * attacked, BattleHex attackFrom = BattleHex::INVALID);
static BattleAction makeShotAttack(const CStack *shooter, const CStack *target);
static BattleAction makeMove(const CStack *stack, BattleHex dest);
static BattleAction makeHeal(const CStack * healer, const CStack * healed);
static BattleAction makeDefend(const CStack * stack);
static BattleAction makeWait(const CStack * stack);
static BattleAction makeMeleeAttack(const CStack * stack, const CStack * attacked, BattleHex attackFrom = BattleHex::INVALID);
static BattleAction makeShotAttack(const CStack * shooter, const CStack * target);
static BattleAction makeMove(const CStack * stack, BattleHex dest);
static BattleAction makeEndOFTacticPhase(ui8 side);
};

View File

@ -0,0 +1,51 @@
/*
* BattleAttackInfo.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
*
*/
#include "StdInc.h"
#include "BattleAttackInfo.h"
#include "CStack.h"
BattleAttackInfo::BattleAttackInfo(const CStack * Attacker, const CStack * Defender, bool Shooting)
{
attacker = Attacker;
defender = Defender;
attackerBonuses = Attacker;
defenderBonuses = Defender;
attackerPosition = Attacker->position;
defenderPosition = Defender->position;
attackerCount = Attacker->count;
defenderCount = Defender->count;
shooting = Shooting;
chargedFields = 0;
luckyHit = false;
unluckyHit = false;
deathBlow = false;
ballistaDoubleDamage = false;
}
BattleAttackInfo BattleAttackInfo::reverse() const
{
BattleAttackInfo ret = *this;
std::swap(ret.attacker, ret.defender);
std::swap(ret.attackerBonuses, ret.defenderBonuses);
std::swap(ret.attackerPosition, ret.defenderPosition);
std::swap(ret.attackerCount, ret.defenderCount);
ret.shooting = false;
ret.chargedFields = 0;
ret.luckyHit = ret.ballistaDoubleDamage = ret.deathBlow = false;
return ret;
}

View File

@ -0,0 +1,33 @@
/*
* BattleAttackInfo.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
*
*/
#pragma once
#include "BattleHex.h"
class CStack;
class IBonusBearer;
struct DLL_LINKAGE BattleAttackInfo
{
const IBonusBearer *attackerBonuses, *defenderBonuses;
const CStack *attacker, *defender;
BattleHex attackerPosition, defenderPosition;
int attackerCount, defenderCount;
bool shooting;
int chargedFields;
bool luckyHit;
bool unluckyHit;
bool deathBlow;
bool ballistaDoubleDamage;
BattleAttackInfo(const CStack * Attacker, const CStack * Defender, bool Shooting = false);
BattleAttackInfo reverse() const;
};

View File

@ -8,7 +8,7 @@
*
*/
#pragma once
#include "GameConstants.h"
#include "../GameConstants.h"
// for battle stacks' positions
struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class for better code design

View File

@ -57,7 +57,7 @@ int BattleInfo::getAvaliableHex(CreatureID creID, bool attackerOwned, int initia
return BattleHex::getClosestTile(attackerOwned, pos, occupyable);
}
std::pair< std::vector<BattleHex>, int > BattleInfo::getPath(BattleHex start, BattleHex dest, const CStack *stack)
std::pair< std::vector<BattleHex>, int > BattleInfo::getPath(BattleHex start, BattleHex dest, const CStack * stack)
{
auto reachability = getReachability(stack);
@ -78,8 +78,8 @@ std::pair< std::vector<BattleHex>, int > BattleInfo::getPath(BattleHex start, Ba
return std::make_pair(path, reachability.distances[dest]);
}
ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender,
bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand )
ui32 BattleInfo::calculateDmg(const CStack* attacker, const CStack* defender,
bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand)
{
TDmgRange range = calculateDmgRange(attacker, defender, shooting, charge, lucky, unlucky, deathBlow, ballistaDoubleDmg);
@ -96,7 +96,7 @@ ui32 BattleInfo::calculateDmg( const CStack* attacker, const CStack* defender,
return range.first;
}
void BattleInfo::calculateCasualties( std::map<ui32,si32> *casualties ) const
void BattleInfo::calculateCasualties(std::map<ui32,si32> * casualties) const
{
for(auto & elem : stacks)//setting casualties
{
@ -112,12 +112,12 @@ CStack * BattleInfo::generateNewStack(const CStackInstance &base, bool attackerO
{
int stackID = getIdForNewStack();
PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
assert((owner >= PlayerColor::PLAYER_LIMIT) ||
(base.armyObj && base.armyObj->tempOwner == owner));
assert((owner >= PlayerColor::PLAYER_LIMIT) ||
(base.armyObj && base.armyObj->tempOwner == owner));
auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
ret->position = getAvaliableHex (base.getCreatureID(), attackerOwned, position); //TODO: what if no free tile on battlefield was found?
ret->state.insert(EBattleStackState::ALIVE); //alive state indication
ret->state.insert(EBattleStackState::ALIVE); //alive state indication
return ret;
}
@ -125,9 +125,9 @@ CStack * BattleInfo::generateNewStack(const CStackBasicDescriptor &base, bool at
{
int stackID = getIdForNewStack();
PlayerColor owner = sides[attackerOwned ? 0 : 1].color;
auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
auto ret = new CStack(&base, owner, stackID, attackerOwned, slot);
ret->position = position;
ret->state.insert(EBattleStackState::ALIVE); //alive state indication
ret->state.insert(EBattleStackState::ALIVE); //alive state indication
return ret;
}
@ -261,7 +261,7 @@ struct RangeGenerator
std::function<int()> myRand;
};
BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town )
BattleInfo * BattleInfo::setupBattle(int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town)
{
CMP_stack cmpst;
auto curB = new BattleInfo();
@ -644,7 +644,7 @@ BattleInfo * BattleInfo::setupBattle( int3 tile, ETerrainType terrain, BFieldTyp
return curB;
}
const CGHeroInstance * BattleInfo::getHero( PlayerColor player ) const
const CGHeroInstance * BattleInfo::getHero(PlayerColor player) const
{
for(int i = 0; i < sides.size(); i++)
if(sides[i].color == player)
@ -741,7 +741,7 @@ CGHeroInstance * BattleInfo::battleGetFightingHero(ui8 side) const
}
bool CMP_stack::operator()( const CStack* a, const CStack* b )
bool CMP_stack::operator()(const CStack* a, const CStack* b)
{
switch(phase)
{
@ -772,7 +772,7 @@ bool CMP_stack::operator()( const CStack* a, const CStack* b )
}
CMP_stack::CMP_stack( int Phase /*= 1*/, int Turn )
CMP_stack::CMP_stack(int Phase /*= 1*/, int Turn)
{
phase = Phase;
turn = Turn;

View File

@ -11,7 +11,7 @@
#include "SiegeInfo.h"
#include "SideInBattle.h"
#include "HeroBonus.h"
#include "CBattleCallback.h"
#include "battle/CBattleInfoCallback.h"
#include "int3.h"
class CStack;
@ -61,7 +61,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
//static bool isAccessible(BattleHex hex, bool * accessibility, bool twoHex, bool attackerOwned, bool flying, bool lastPos); //helper for makeBFS
int getAvaliableHex(CreatureID creID, bool attackerOwned, int initialPos = -1) const; //find place for summon / clone effects
//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::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 = nullptr, bool forPassingBy = false) const; //returns vector of accessible tiles (taking into account the creature range)
//bool isObstacleVisibleForSide(const CObstacleInstance &obstacle, ui8 side) const;
@ -69,7 +69,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
std::set<BattleHex> getStoppers(bool whichSidePerspective) const;
ui32 calculateDmg(const CStack * attacker, const CStack * defender, bool shooting, ui8 charge, bool lucky, bool unlucky, bool deathBlow, bool ballistaDoubleDmg, CRandomGenerator & rand); //charge - number of hexes travelled before attack (for champion's jousting)
void calculateCasualties(std::map<ui32,si32> *casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
void calculateCasualties(std::map<ui32,si32> * casualties) const; //casualties are array of maps size 2 (attacker, defeneder), maps are (crid => amount)
//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
@ -84,7 +84,7 @@ struct DLL_LINKAGE BattleInfo : public CBonusSystemNode, public CBattleInfoCallb
void localInit();
void localInitStack(CStack * s);
static BattleInfo * setupBattle( int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance *armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance *town );
static BattleInfo * setupBattle(int3 tile, ETerrainType terrain, BFieldType battlefieldType, const CArmedInstance * armies[2], const CGHeroInstance * heroes[2], bool creatureBank, const CGTownInstance * town);
//bool hasNativeStack(ui8 side) const;
PlayerColor theOtherPlayer(PlayerColor player) const;

View File

@ -0,0 +1,110 @@
/*
* 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
*
*/
#pragma once
#include "CCallbackBase.h"
#include "ReachabilityInfo.h"
#include "BattleAttackInfo.h"
class CGHeroInstance;
class CStack;
class ISpellCaster;
class CSpell;
struct CObstacleInstance;
class IBonusBearer;
class CRandomGenerator;
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;
}
};
class DLL_LINKAGE CBattleInfoCallback : public virtual CBattleInfoEssentials
{
public:
enum ERandomSpell
{
RANDOM_GENIE, RANDOM_AIMED
};
//battle
boost::optional<int> battleIsFinished() const; //return none if battle is ongoing; otherwise the victorious side (0/1) or 2 if it is a draw
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)
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
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
int battleGetSurrenderCost(PlayerColor Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible
ReachabilityInfo::TDistances battleGetDistances(const CStack * stack, BattleHex hex = BattleHex::INVALID, BattleHex * predecessors = nullptr) const; //returns vector of distances to [dest hex number]
std::set<BattleHex> battleGetAttackedHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const;
bool battleCanAttack(const CStack * stack, const CStack * target, BattleHex dest) const; //determines if stack with given ID can attack target at the selected destination
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;
TDmgRange calculateDmgRange(const BattleAttackInfo & info) 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, 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>
//hextowallpart //int battleGetWallUnderHex(BattleHex hex) const; //returns part of destructible wall / gate / keep under given hex or -1 if not found
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>
si8 battleHasDistancePenalty(const CStack * stack, BattleHex destHex) const;
si8 battleHasDistancePenalty(const IBonusBearer * bonusBearer, BattleHex shooterPosition, BattleHex destHex) const;
si8 battleHasWallPenalty(const CStack * stack, BattleHex destHex) const; //checks if given stack has wall penalty
si8 battleHasWallPenalty(const IBonusBearer * bonusBearer, BattleHex shooterPosition, BattleHex destHex) const; //checks if given stack has wall penalty
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;
//*** MAGIC
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
ui32 battleGetSpellCost(const CSpell * sp, const CGHeroInstance * caster) const; //returns cost of given spell
ESpellCastProblem::ESpellCastProblem battleCanCastSpell(const ISpellCaster * caster, ECastingMode::ECastingMode mode) const; //returns true if there are no general issues preventing from casting a spell
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
const CStack * getStackIf(std::function<bool(const CStack*)> pred) const;
si8 battleHasShootingPenalty(const CStack * stack, BattleHex 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)
AttackableTiles getPotentiallyAttackableHexes(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos) const; //TODO: apply rotation to two-hex attacker
std::set<const CStack*> getAttackedCreatures(const CStack* attacker, BattleHex destinationTile, BattleHex attackerPos = BattleHex::INVALID) const; //calculates range of multi-hex attacks
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
ReachabilityInfo getReachability(const CStack *stack) const;
ReachabilityInfo getReachability(const ReachabilityInfo::Parameters & params) const;
AccessibilityInfo getAccesibility() const;
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
std::pair<const CStack *, BattleHex> getNearestStack(const CStack * closest, boost::logic::tribool attackerOwned) const;
protected:
ReachabilityInfo getFlyingReachability(const ReachabilityInfo::Parameters & params) const;
ReachabilityInfo makeBFS(const AccessibilityInfo & accessibility, const ReachabilityInfo::Parameters & params) const;
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)
};

View File

@ -0,0 +1,349 @@
/*
* CBattleInfoEssentials.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
*
*/
#include "StdInc.h"
#include "CBattleInfoEssentials.h"
#include "CStack.h"
#include "BattleInfo.h"
#include "NetPacks.h"
#include "mapObjects/CGTownInstance.h"
ETerrainType CBattleInfoEssentials::battleTerrainType() const
{
RETURN_IF_NOT_BATTLE(ETerrainType::WRONG);
return getBattle()->terrainType;
}
BFieldType CBattleInfoEssentials::battleGetBattlefieldType() const
{
RETURN_IF_NOT_BATTLE(BFieldType::NONE);
return getBattle()->battlefieldType;
}
std::vector<std::shared_ptr<const CObstacleInstance> > CBattleInfoEssentials::battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective /*= boost::none*/) const
{
std::vector<std::shared_ptr<const CObstacleInstance> > ret;
RETURN_IF_NOT_BATTLE(ret);
if(!perspective)
{
//if no particular perspective request, use default one
perspective = battleGetMySide();
}
else
{
if(!!player && *perspective != battleGetMySide())
{
logGlobal->error("Unauthorized access attempt!");
assert(0); //I want to notice if that happens
//perspective = battleGetMySide();
}
}
for(auto oi : getBattle()->obstacles)
{
if(getBattle()->battleIsObstacleVisibleForSide(*oi, *perspective))
ret.push_back(oi);
}
return ret;
}
bool CBattleInfoEssentials::battleIsObstacleVisibleForSide(const CObstacleInstance & coi, BattlePerspective::BattlePerspective side) const
{
RETURN_IF_NOT_BATTLE(false);
return side == BattlePerspective::ALL_KNOWING || coi.visibleForSide(side, battleHasNativeStack(side));
}
bool CBattleInfoEssentials::battleHasNativeStack(ui8 side) const
{
RETURN_IF_NOT_BATTLE(false);
for(const CStack * s : battleGetAllStacks())
{
if(s->attackerOwned == !side && s->getCreature()->isItNativeTerrain(getBattle()->terrainType))
return true;
}
return false;
}
TStacks CBattleInfoEssentials::battleGetAllStacks(bool includeTurrets /*= false*/) const
{
return battleGetStacksIf([=](const CStack * s)
{
return !s->isGhost() && (includeTurrets || !s->isTurret());
});
}
TStacks CBattleInfoEssentials::battleGetStacksIf(TStackFilter predicate) const
{
TStacks ret;
RETURN_IF_NOT_BATTLE(ret);
vstd::copy_if(getBattle()->stacks, std::back_inserter(ret), predicate);
return ret;
}
TStacks CBattleInfoEssentials::battleAliveStacks() const
{
return battleGetStacksIf([](const CStack * s){
return s->isValidTarget(false);
});
}
TStacks CBattleInfoEssentials::battleAliveStacks(ui8 side) const
{
return battleGetStacksIf([=](const CStack * s){
return s->isValidTarget(false) && s->attackerOwned == !side;
});
}
int CBattleInfoEssentials::battleGetMoatDmg() const
{
RETURN_IF_NOT_BATTLE(0);
auto town = getBattle()->town;
if(!town)
return 0;
return town->town->moatDamage;
}
const CGTownInstance * CBattleInfoEssentials::battleGetDefendedTown() const
{
RETURN_IF_NOT_BATTLE(nullptr);
if(!getBattle() || getBattle()->town == nullptr)
return nullptr;
return getBattle()->town;
}
BattlePerspective::BattlePerspective CBattleInfoEssentials::battleGetMySide() const
{
RETURN_IF_NOT_BATTLE(BattlePerspective::INVALID);
if(!player || player.get().isSpectator())
return BattlePerspective::ALL_KNOWING;
if(*player == getBattle()->sides[0].color)
return BattlePerspective::LEFT_SIDE;
if(*player == getBattle()->sides[1].color)
return BattlePerspective::RIGHT_SIDE;
logGlobal->errorStream() << "Cannot find player " << *player << " in battle!";
return BattlePerspective::INVALID;
}
const CStack * CBattleInfoEssentials::battleActiveStack() const
{
RETURN_IF_NOT_BATTLE(nullptr);
return battleGetStackByID(getBattle()->activeStack);
}
const CStack* CBattleInfoEssentials::battleGetStackByID(int ID, bool onlyAlive) const
{
RETURN_IF_NOT_BATTLE(nullptr);
auto stacks = battleGetStacksIf([=](const CStack * s)
{
return s->ID == ID && (!onlyAlive || s->alive());
});
if(stacks.empty())
return nullptr;
else
return stacks[0];
}
bool CBattleInfoEssentials::battleDoWeKnowAbout(ui8 side) const
{
RETURN_IF_NOT_BATTLE(false);
auto p = battleGetMySide();
return p == BattlePerspective::ALL_KNOWING || p == side;
}
si8 CBattleInfoEssentials::battleTacticDist() const
{
RETURN_IF_NOT_BATTLE(0);
return getBattle()->tacticDistance;
}
si8 CBattleInfoEssentials::battleGetTacticsSide() const
{
RETURN_IF_NOT_BATTLE(-1);
return getBattle()->tacticsSide;
}
const CGHeroInstance * CBattleInfoEssentials::battleGetFightingHero(ui8 side) const
{
RETURN_IF_NOT_BATTLE(nullptr);
if(side > 1)
{
logGlobal->errorStream() << "FIXME: " << __FUNCTION__ << " wrong argument!";
return nullptr;
}
if(!battleDoWeKnowAbout(side))
{
logGlobal->errorStream() << "FIXME: " << __FUNCTION__ << " access check ";
return nullptr;
}
return getBattle()->sides[side].hero;
}
const CArmedInstance * CBattleInfoEssentials::battleGetArmyObject(ui8 side) const
{
RETURN_IF_NOT_BATTLE(nullptr);
if(side > 1)
{
logGlobal->errorStream() << "FIXME: " << __FUNCTION__ << " wrong argument!";
return nullptr;
}
if(!battleDoWeKnowAbout(side))
{
logGlobal->errorStream() << "FIXME: " << __FUNCTION__ << " access check ";
return nullptr;
}
return getBattle()->sides[side].armyObject;
}
InfoAboutHero CBattleInfoEssentials::battleGetHeroInfo(ui8 side) const
{
auto hero = getBattle()->sides[side].hero;
if(!hero)
{
logGlobal->warnStream() << __FUNCTION__ << ": side " << (int)side << " does not have hero!";
return InfoAboutHero();
}
InfoAboutHero::EInfoLevel infoLevel = battleDoWeKnowAbout(side) ? InfoAboutHero::EInfoLevel::DETAILED : InfoAboutHero::EInfoLevel::BASIC;
return InfoAboutHero(hero, infoLevel);
}
int CBattleInfoEssentials::battleCastSpells(ui8 side) const
{
RETURN_IF_NOT_BATTLE(-1);
return getBattle()->sides[side].castSpellsCount;
}
const IBonusBearer * CBattleInfoEssentials::getBattleNode() const
{
return getBattle();
}
bool CBattleInfoEssentials::battleCanFlee(PlayerColor player) const
{
RETURN_IF_NOT_BATTLE(false);
const si8 mySide = playerToSide(player);
const CGHeroInstance *myHero = battleGetFightingHero(mySide);
//current player have no hero
if(!myHero)
return false;
//eg. one of heroes is wearing shakles of war
if(myHero->hasBonusOfType(Bonus::BATTLE_NO_FLEEING))
return false;
//we are besieged defender
if(mySide == BattleSide::DEFENDER && battleGetSiegeLevel())
{
auto town = battleGetDefendedTown();
if(!town->hasBuilt(BuildingID::ESCAPE_TUNNEL, ETownType::STRONGHOLD))
return false;
}
return true;
}
si8 CBattleInfoEssentials::playerToSide(PlayerColor player) const
{
RETURN_IF_NOT_BATTLE(-1);
int ret = vstd::find_pos_if(getBattle()->sides, [=](const SideInBattle &side){ return side.color == player; });
if(ret < 0)
logGlobal->warnStream() << "Cannot find side for player " << player;
return ret;
}
bool CBattleInfoEssentials::playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const
{
RETURN_IF_NOT_BATTLE(false);
const si8 playerSide = playerToSide(player);
if (playerSide >= 0)
{
if (getBattle()->sides[!playerSide].hero == h)
return true;
}
return false;
}
ui8 CBattleInfoEssentials::battleGetSiegeLevel() const
{
RETURN_IF_NOT_BATTLE(0);
return getBattle()->town ? getBattle()->town->fortLevel() : CGTownInstance::NONE;
}
bool CBattleInfoEssentials::battleCanSurrender(PlayerColor player) const
{
RETURN_IF_NOT_BATTLE(false);
ui8 mySide = playerToSide(player);
bool iAmSiegeDefender = (mySide == BattleSide::DEFENDER && battleGetSiegeLevel());
//conditions like for fleeing (except escape tunnel presence) + enemy must have a hero
return battleCanFlee(player) && !iAmSiegeDefender && battleHasHero(!mySide);
}
bool CBattleInfoEssentials::battleHasHero(ui8 side) const
{
RETURN_IF_NOT_BATTLE(false);
assert(side < 2);
return getBattle()->sides[side].hero;
}
si8 CBattleInfoEssentials::battleGetWallState(int partOfWall) const
{
RETURN_IF_NOT_BATTLE(0);
if(getBattle()->town == nullptr || getBattle()->town->fortLevel() == CGTownInstance::NONE)
return EWallState::NONE;
assert(partOfWall >= 0 && partOfWall < EWallPart::PARTS_COUNT);
return getBattle()->si.wallState[partOfWall];
}
EGateState CBattleInfoEssentials::battleGetGateState() const
{
RETURN_IF_NOT_BATTLE(EGateState::NONE);
if(getBattle()->town == nullptr || getBattle()->town->fortLevel() == CGTownInstance::NONE)
return EGateState::NONE;
return getBattle()->si.gateState;
}
PlayerColor CBattleInfoEssentials::battleGetOwner(const CStack * stack) const
{
RETURN_IF_NOT_BATTLE(PlayerColor::CANNOT_DETERMINE);
if(stack->hasBonusOfType(Bonus::HYPNOTIZED))
return getBattle()->theOtherPlayer(stack->owner);
else
return stack->owner;
}
const CGHeroInstance * CBattleInfoEssentials::battleGetOwnerHero(const CStack * stack) const
{
RETURN_IF_NOT_BATTLE(nullptr);
return getBattle()->sides.at(playerToSide(battleGetOwner(stack))).hero;
}
bool CBattleInfoEssentials::battleMatchOwner(const CStack * attacker, const CStack * defender, const boost::logic::tribool positivness /* = false*/) const
{
RETURN_IF_NOT_BATTLE(false);
if(boost::logic::indeterminate(positivness))
return true;
else if(defender->owner != battleGetOwner(defender))
return true; //mind controlled unit is attackable for both sides
else
return (battleGetOwner(attacker) == battleGetOwner(defender)) == positivness;
}

View File

@ -0,0 +1,108 @@
/*
* CBattleInfoEssentials.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
*
*/
#pragma once
#include "CCallbackBase.h"
class CGTownInstance;
class CGHeroInstance;
class CStack;
struct CObstacleInstance;
class IBonusBearer;
struct InfoAboutHero;
class CArmedInstance;
typedef std::vector<const CStack*> TStacks;
typedef std::function<bool(const CStack *)> TStackFilter;
namespace BattlePerspective
{
enum BattlePerspective
{
INVALID = -2,
ALL_KNOWING = -1,
LEFT_SIDE,
RIGHT_SIDE
};
}
namespace BattleSide
{
enum {ATTACKER = 0, DEFENDER = 1};
}
class DLL_LINKAGE CBattleInfoEssentials : public virtual CCallbackBase
{
protected:
bool battleDoWeKnowAbout(ui8 side) const;
const IBonusBearer * getBattleNode() const;
public:
enum EStackOwnership
{
ONLY_MINE, ONLY_ENEMY, MINE_AND_ENEMY
};
BattlePerspective::BattlePerspective battleGetMySide() const;
ETerrainType battleTerrainType() const;
BFieldType battleGetBattlefieldType() const;
std::vector<std::shared_ptr<const CObstacleInstance> > battleGetAllObstacles(boost::optional<BattlePerspective::BattlePerspective> perspective = boost::none) const; //returns all obstacles on the battlefield
/** @brief Main method for getting battle stacks
*
* @param predicate Functor that shall return true for desired stack
* @return filtered stacks
*
*/
TStacks battleGetStacksIf(TStackFilter predicate) const;
bool battleHasNativeStack(ui8 side) const;
int battleGetMoatDmg() const; //what dmg unit will suffer if ending turn in the moat
const CGTownInstance * battleGetDefendedTown() const; //returns defended town if current battle is a siege, nullptr instead
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 (?)
bool battleCanFlee(PlayerColor player) const;
bool battleCanSurrender(PlayerColor player) const;
si8 playerToSide(PlayerColor player) const;
bool playerHasAccessToHeroInfo(PlayerColor player, const CGHeroInstance * h) const;
ui8 battleGetSiegeLevel() const; //returns 0 when there is no siege, 1 if fort, 2 is citadel, 3 is castle
bool battleHasHero(ui8 side) const;
int battleCastSpells(ui8 side) const; //how many spells has given side cast
const CGHeroInstance * battleGetFightingHero(ui8 side) const; //depracated for players callback, easy to get wrong
const CArmedInstance * battleGetArmyObject(ui8 side) const;
InfoAboutHero battleGetHeroInfo(ui8 side) const;
// 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;
EGateState battleGetGateState() const;
//helpers
///returns all stacks, alive or dead or undead or mechanical :)
TStacks battleGetAllStacks(bool includeTurrets = false) const;
///returns all alive stacks excluding turrets
TStacks battleAliveStacks() const;
///returns all alive stacks from particular side excluding turrets
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;
///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;
};

View File

@ -0,0 +1,42 @@
/*
* CCallbackBase.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
*
*/
#include "StdInc.h"
#include "CCallbackBase.h"
#include "BattleInfo.h"
#include "CGameState.h"
bool CCallbackBase::duringBattle() const
{
return getBattle() != nullptr;
}
const BattleInfo *CCallbackBase::getBattle() const
{
return battle;
}
CCallbackBase::CCallbackBase(CGameState * GS, boost::optional<PlayerColor> Player)
: battle(nullptr), gs(GS), player(Player)
{}
CCallbackBase::CCallbackBase()
: battle(nullptr), gs(nullptr)
{}
void CCallbackBase::setBattle(const BattleInfo * B)
{
battle = B;
}
boost::optional<PlayerColor> CCallbackBase::getPlayerID() const
{
return player;
}

View File

@ -0,0 +1,42 @@
/*
* CCallbackBase.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
*
*/
#pragma once
#include "GameConstants.h"
#define RETURN_IF_NOT_BATTLE(X) if(!duringBattle()) {logGlobal->errorStream() << __FUNCTION__ << " called when no battle!"; return X; }
class CGameState;
struct BattleInfo;
class CBattleInfoEssentials;
//Basic class for various callbacks (interfaces called by players to get info about game and so forth)
class DLL_LINKAGE CCallbackBase
{
const BattleInfo * battle; //battle to which the player is engaged, nullptr if none or not applicable
const BattleInfo * getBattle() const;
protected:
CGameState * gs;
boost::optional<PlayerColor> player; // not set gives access to all information, otherwise callback provides only information "visible" for player
CCallbackBase(CGameState * GS, boost::optional<PlayerColor> Player);
CCallbackBase();
void setBattle(const BattleInfo * B);
bool duringBattle() const;
public:
boost::optional<PlayerColor> getPlayerID() const;
friend class CBattleInfoEssentials;
};

View File

@ -69,7 +69,7 @@ std::vector<BattleHex> CObstacleInstance::getAffectedTiles() const
// bool CObstacleInstance::spellGenerated() const
// {
// if(obstacleType == USUAL || obstacleType == ABSOLUTE_OBSTACLE)
// if(obstacleType == USUAL || obstacleType == ABSOLUTE_OBSTACLE)
// return false;
//
// return true;
@ -83,12 +83,12 @@ bool CObstacleInstance::visibleForSide(ui8 side, bool hasNativeStack) const
bool CObstacleInstance::stopsMovement() const
{
return obstacleType == QUICKSAND || obstacleType == MOAT;
return obstacleType == QUICKSAND || obstacleType == MOAT;
}
bool CObstacleInstance::blocksTiles() const
{
return obstacleType == USUAL || obstacleType == ABSOLUTE_OBSTACLE || obstacleType == FORCE_FIELD;
return obstacleType == USUAL || obstacleType == ABSOLUTE_OBSTACLE || obstacleType == FORCE_FIELD;
}
SpellCreatedObstacle::SpellCreatedObstacle()
@ -113,7 +113,7 @@ bool SpellCreatedObstacle::visibleForSide(ui8 side, bool hasNativeStack) const
//we hide mines and not discovered quicksands
//quicksands are visible to the caster or if owned unit stepped into that particular patch
//additionally if side has a native unit, mines/quicksands will be visible
return casterSide == side || visibleForAnotherSide || hasNativeStack;
return casterSide == side || visibleForAnotherSide || hasNativeStack;
default:
assert(0);
return false;

View File

@ -0,0 +1,54 @@
/*
* CPlayerBattleCallback.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
*
*/
#include "StdInc.h"
#include "CPlayerBattleCallback.h"
#include "CStack.h"
#include "CGameState.h"
bool CPlayerBattleCallback::battleCanFlee() const
{
RETURN_IF_NOT_BATTLE(false);
ASSERT_IF_CALLED_WITH_PLAYER
return CBattleInfoEssentials::battleCanFlee(*player);
}
TStacks CPlayerBattleCallback::battleGetStacks(EStackOwnership whose /*= MINE_AND_ENEMY*/, bool onlyAlive /*= true*/) const
{
if(whose != MINE_AND_ENEMY)
{
ASSERT_IF_CALLED_WITH_PLAYER
}
return battleGetStacksIf([=](const CStack * s){
const bool ownerMatches = (whose == MINE_AND_ENEMY)
|| (whose == ONLY_MINE && s->owner == player)
|| (whose == ONLY_ENEMY && s->owner != player);
return ownerMatches && s->isValidTarget(!onlyAlive);
});
}
int CPlayerBattleCallback::battleGetSurrenderCost() const
{
RETURN_IF_NOT_BATTLE(-3)
ASSERT_IF_CALLED_WITH_PLAYER
return CBattleInfoCallback::battleGetSurrenderCost(*player);
}
const CGHeroInstance * CPlayerBattleCallback::battleGetMyHero() const
{
return CBattleInfoEssentials::battleGetFightingHero(battleGetMySide());
}
InfoAboutHero CPlayerBattleCallback::battleGetEnemyHero() const
{
return battleGetHeroInfo(!battleGetMySide());
}

View File

@ -0,0 +1,26 @@
/*
* CPlayerBattleCallback.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
*
*/
#pragma once
#include "CBattleInfoCallback.h"
class CGHeroInstance;
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
int battleGetSurrenderCost() const; //returns cost of surrendering battle, -1 if surrendering is not possible
const CGHeroInstance * battleGetMyHero() const;
InfoAboutHero battleGetEnemyHero() const;
};

View File

@ -0,0 +1,43 @@
/*
* ReachabilityInfo.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
*
*/
#include "StdInc.h"
#include "ReachabilityInfo.h"
#include "CStack.h"
ReachabilityInfo::Parameters::Parameters()
{
stack = nullptr;
perspective = BattlePerspective::ALL_KNOWING;
attackerOwned = doubleWide = flying = false;
}
ReachabilityInfo::Parameters::Parameters(const CStack * Stack)
{
stack = Stack;
perspective = (BattlePerspective::BattlePerspective)(!Stack->attackerOwned);
startPosition = Stack->position;
doubleWide = stack->doubleWide();
attackerOwned = stack->attackerOwned;
flying = stack->hasBonusOfType(Bonus::FLYING);
knownAccessible = stack->getHexes();
}
ReachabilityInfo::ReachabilityInfo()
{
distances.fill(INFINITE_DIST);
predecessors.fill(BattleHex::INVALID);
}
bool ReachabilityInfo::isReachable(BattleHex hex) const
{
return distances[hex] < INFINITE_DIST;
}

View File

@ -0,0 +1,52 @@
/*
* ReachabilityInfo.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
*
*/
#pragma once
#include "BattleHex.h"
#include "CBattleInfoEssentials.h"
#include "AccessibilityInfo.h"
class CStack;
// Reachability info is result of BFS calculation. It's dependent on stack (it's owner, whether it's flying),
// startPosition and perpective.
struct DLL_LINKAGE ReachabilityInfo
{
typedef std::array<int, GameConstants::BFIELD_SIZE> TDistances;
typedef std::array<BattleHex, GameConstants::BFIELD_SIZE> TPredecessors;
enum { INFINITE_DIST = 1000000 };
struct DLL_LINKAGE Parameters
{
const CStack * stack; //stack for which calculation is mage => not required (kept for debugging mostly), following variables are enough
bool attackerOwned;
bool doubleWide;
bool flying;
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)
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();
bool isReachable(BattleHex hex) const;
};

View File

@ -11,7 +11,7 @@
#include "../mapObjects/CRewardableConstructor.h"
#include "../mapObjects/CommonConstructors.h"
#include "../mapObjects/MapObjects.h"
#include "../CObstacleInstance.h"
#include "../battle/CObstacleInstance.h"
/*
* RegisterTypes.h, part of VCMI engine

View File

@ -3,7 +3,7 @@
#include "../StartInfo.h"
#include "../CStack.h"
#include "../BattleInfo.h"
#include "../battle/BattleInfo.h"
#include "../CGameState.h"
#include "../mapping/CMap.h"
#include "../CModHandler.h"

View File

@ -3,7 +3,7 @@
#include "../StartInfo.h"
#include "../CStack.h"
#include "../BattleInfo.h"
#include "../battle/BattleInfo.h"
#include "../CGameState.h"
#include "../mapping/CMap.h"
#include "../CModHandler.h"

View File

@ -13,7 +13,7 @@
#include "../NetPacks.h"
#include "../CStack.h"
#include "../BattleInfo.h"
#include "../battle/BattleInfo.h"
#include "../mapObjects/CGHeroInstance.h"
#include "../mapObjects/CGTownInstance.h"

View File

@ -13,7 +13,7 @@
#include "CDefaultSpellMechanics.h"
#include "../CStack.h"
#include "../BattleInfo.h"
#include "../battle/BattleInfo.h"
#include "../CGeneralTextHandler.h"

View File

@ -23,8 +23,8 @@
#include "../StringConstants.h"
#include "../CStack.h"
#include "../BattleInfo.h"
#include "../CBattleCallback.h"
#include "../battle/BattleInfo.h"
#include "../battle/CBattleInfoCallback.h"
#include "../CGameState.h" //todo: remove
#include "../NetPacks.h" //todo: remove

View File

@ -14,7 +14,7 @@
#include "../ConstTransitivePtr.h"
#include "../int3.h"
#include "../GameConstants.h"
#include "../BattleHex.h"
#include "../battle/BattleHex.h"
#include "../HeroBonus.h"
class CGObjectInstance;

View File

@ -14,7 +14,7 @@
#include "../NetPacks.h"
#include "../CStack.h"
#include "../BattleInfo.h"
#include "../battle/BattleInfo.h"
///AcidBreathDamageMechanics
void AcidBreathDamageMechanics::applyBattleEffects(const SpellCastEnvironment * env, const BattleSpellCastParameters & parameters, SpellCastContext & ctx) const

View File

@ -12,7 +12,7 @@
#include "ISpellMechanics.h"
#include "../CStack.h"
#include "../BattleInfo.h"
#include "../battle/BattleInfo.h"
#include "../NetPacks.h"

View File

@ -11,7 +11,7 @@
#pragma once
#include "CSpellHandler.h"
#include "../BattleHex.h"
#include "../battle/BattleHex.h"
///callback to be provided by server

View File

@ -16,7 +16,7 @@
#include "../lib/CCreatureHandler.h"
#include "../lib/CGameState.h"
#include "../lib/CStack.h"
#include "../lib/BattleInfo.h"
#include "../lib/battle/BattleInfo.h"
#include "../lib/CondSh.h"
#include "../lib/NetPacks.h"
#include "../lib/VCMI_Lib.h"

View File

@ -3,7 +3,7 @@
#include "../lib/FunctionList.h"
#include "../lib/IGameCallback.h"
#include "../lib/BattleAction.h"
#include "../lib/battle/BattleAction.h"
#include "CQuery.h"

View File

@ -1,7 +1,7 @@
#include "StdInc.h"
#include "CQuery.h"
#include "CGameHandler.h"
#include "../lib/BattleInfo.h"
#include "../lib/battle/BattleInfo.h"
#include "../lib/mapObjects/MiscObjects.h"
boost::mutex Queries::mx;

View File

@ -6,8 +6,8 @@
#include "../lib/mapping/CMap.h"
#include "../lib/CGameState.h"
#include "../lib/CStack.h"
#include "../lib/BattleInfo.h"
#include "../lib/BattleAction.h"
#include "../lib/battle/BattleInfo.h"
#include "../lib/battle/BattleAction.h"
#include "../lib/serializer/Connection.h"

View File

@ -9,7 +9,7 @@
*/
#include "StdInc.h"
#include <boost/test/unit_test.hpp>
#include "../lib/BattleHex.h"
#include "../lib/battle/BattleHex.h"
BOOST_AUTO_TEST_SUITE(BattlefieldHex_Suite)
BOOST_AUTO_TEST_CASE(getNeighbouringTiles)