1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232
|
/*
* BattleInterface.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 "BattleConstants.h"
#include "../lib/battle/BattleHex.h"
#include "../gui/CIntObject.h"
#include "../../lib/spells/CSpellHandler.h" //CSpell::TAnimation
#include "../ConditionalWait.h"
VCMI_LIB_NAMESPACE_BEGIN
class CCreatureSet;
class CGHeroInstance;
class CStack;
struct BattleResult;
struct BattleSpellCast;
struct CObstacleInstance;
struct SetStackEffect;
class BattleAction;
class CGTownInstance;
struct CatapultAttack;
struct BattleTriggerEffect;
struct InfoAboutHero;
class ObstacleChanges;
class CPlayerBattleCallback;
VCMI_LIB_NAMESPACE_END
class BattleHero;
class Canvas;
class BattleResultWindow;
class StackQueue;
class CPlayerInterface;
struct BattleEffect;
class IImage;
class StackQueue;
class BattleProjectileController;
class BattleSiegeController;
class BattleObstacleController;
class BattleFieldController;
class BattleRenderer;
class BattleWindow;
class BattleStacksController;
class BattleActionsController;
class BattleEffectsController;
class BattleConsole;
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
struct StackAttackedInfo
{
const CStack *defender;
const CStack *attacker;
int64_t damageDealt;
uint32_t amountKilled;
SpellID spellEffect;
bool indirectAttack; //if true, stack was attacked indirectly - spell or ranged attack
bool killed; //if true, stack has been killed
bool rebirth; //if true, play rebirth animation after all
bool cloneKilled;
bool fireShield;
};
struct StackAttackInfo
{
const CStack *attacker;
const CStack *defender;
std::vector< const CStack *> secondaryDefender;
SpellID spellEffect;
BattleHex tile;
bool indirectAttack;
bool lucky;
bool unlucky;
bool deathBlow;
bool lifeDrain;
};
/// Main class for battles, responsible for relaying information from server to various battle entities
class BattleInterface
{
using AwaitingAnimationAction = std::function<void()>;
struct AwaitingAnimationEvents {
AwaitingAnimationAction action;
EAnimationEvents event;
};
/// Conditional variables that are set depending on ongoing animations on the battlefield
ConditionalWait ongoingAnimationsState;
/// List of events that are waiting to be triggered
std::vector<AwaitingAnimationEvents> awaitingEvents;
/// used during tactics mode, points to the interface of player with higher tactics (can be either attacker or defender in hot-seat), valid onloy for human players
std::shared_ptr<CPlayerInterface> tacticianInterface;
/// attacker interface, not null if attacker is human in our vcmiclient
std::shared_ptr<CPlayerInterface> attackerInt;
/// defender interface, not null if attacker is human in our vcmiclient
std::shared_ptr<CPlayerInterface> defenderInt;
/// if set to true, battle is still starting and waiting for intro sound to end / key press from player
bool battleOpeningDelayActive;
/// ID of ongoing battle
BattleID battleID;
void playIntroSoundAndUnlockInterface();
void onIntroSoundPlayed();
public:
/// copy of initial armies (for result window)
const CCreatureSet *army1;
const CCreatureSet *army2;
std::shared_ptr<BattleWindow> windowObject;
std::shared_ptr<BattleConsole> console;
/// currently active player interface
std::shared_ptr<CPlayerInterface> curInt;
const CGHeroInstance *attackingHeroInstance;
const CGHeroInstance *defendingHeroInstance;
bool tacticsMode;
ui32 round;
std::unique_ptr<BattleProjectileController> projectilesController;
std::unique_ptr<BattleSiegeController> siegeController;
std::unique_ptr<BattleObstacleController> obstacleController;
std::unique_ptr<BattleFieldController> fieldController;
std::unique_ptr<BattleStacksController> stacksController;
std::unique_ptr<BattleActionsController> actionsController;
std::unique_ptr<BattleEffectsController> effectsController;
std::shared_ptr<BattleHero> attackingHero;
std::shared_ptr<BattleHero> defendingHero;
bool openingPlaying() const;
void openingEnd();
bool makingTurn() const;
BattleID getBattleID() const;
std::shared_ptr<CPlayerBattleCallback> getBattle() const;
BattleInterface(const BattleID & battleID, const CCreatureSet *army1, const CCreatureSet *army2, const CGHeroInstance *hero1, const CGHeroInstance *hero2, std::shared_ptr<CPlayerInterface> att, std::shared_ptr<CPlayerInterface> defen, std::shared_ptr<CPlayerInterface> spectatorInt = nullptr);
~BattleInterface();
void trySetActivePlayer( PlayerColor player ); // if in hotseat, will activate interface of chosen player
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
void requestAutofightingAIToTakeAction();
void giveCommand(EActionType action, const BattleHex & tile = BattleHex(), SpellID spell = SpellID::NONE);
void sendCommand(BattleAction command, const CStack * actor = nullptr);
const CGHeroInstance *getActiveHero(); //returns hero that can currently cast a spell
void showInterface(Canvas & to);
void setHeroAnimation(BattleSide side, EHeroAnimType phase);
void executeSpellCast(); //called when a hero casts a spell
void appendBattleLog(const std::string & newEntry);
void redrawBattlefield(); //refresh GUI after changing stack range / grid settings
CPlayerInterface *getCurrentPlayerInterface() const;
void tacticNextStack(const CStack *current);
void tacticPhaseEnd();
void setBattleQueueVisibility(bool visible);
void setStickyHeroWindowsVisibility(bool visible);
void setStickyQuickSpellWindowVisibility(bool visible);
void endNetwork();
void executeStagedAnimations();
void executeAnimationStage( EAnimationEvents event);
void onAnimationsStarted();
void onAnimationsFinished();
void waitForAnimations();
bool hasAnimations();
void checkForAnimations();
void addToAnimationStage( EAnimationEvents event, const AwaitingAnimationAction & action);
//call-ins
void startAction(const BattleAction & action);
void stackReset(const CStack * stack);
void stackAdded(const CStack * stack); //new stack appeared on battlefield
void stackRemoved(uint32_t stackID); //stack disappeared from batlefiled
void stackActivated(const CStack *stack); //active stack has been changed
void stackMoved(const CStack *stack, const BattleHexArray & destHex, int distance, bool teleport); //stack with id number moved to destHex
void stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos); //called when a certain amount of stacks has been attacked
void stackAttacking(const StackAttackInfo & attackInfo); //called when stack with id ID is attacking something on hex dest
void newRoundFirst();
void newRound(); //called when round is ended;
void stackIsCatapulting(const CatapultAttack & ca); //called when a stack is attacking walls
void battleFinished(const BattleResult& br, QueryID queryID); //called when battle is finished - battleresult window should be printed
void spellCast(const BattleSpellCast *sc); //called when a hero casts a spell
void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
void castThisSpell(SpellID spellID); //called when player has chosen a spell from spellbook
void displayBattleLog(const std::vector<MetaString> & battleLog);
void displaySpellAnimationQueue(const CSpell * spell, const CSpell::TAnimationQueue & q, const BattleHex & destinationTile, bool isHit);
void displaySpellCast(const CSpell * spell, const BattleHex & destinationTile); //displays spell`s cast animation
void displaySpellEffect(const CSpell * spell, const BattleHex & destinationTile); //displays spell`s affected animation
void displaySpellHit(const CSpell * spell, const BattleHex & destinationTile); //displays spell`s affected animation
void endAction(const BattleAction & action);
void obstaclePlaced(const std::vector<std::shared_ptr<const CObstacleInstance>> oi);
void obstacleRemoved(const std::vector<ObstacleChanges> & obstacles);
void gateStateChanged(const EGateState state);
const CGHeroInstance *currentHero() const;
InfoAboutHero enemyHero() const;
};
|