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
|
/*
* BattleStacksController.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 "../render/ColorFilter.h"
VCMI_LIB_NAMESPACE_BEGIN
class BattleHex;
class BattleHexArray;
class BattleAction;
class CStack;
class CSpell;
class SpellID;
class Point;
VCMI_LIB_NAMESPACE_END
struct StackAttackedInfo;
struct StackAttackInfo;
class ColorFilter;
class Canvas;
class BattleInterface;
class BattleAnimation;
class CreatureAnimation;
class BattleAnimation;
class BattleRenderer;
class IImage;
struct BattleStackFilterEffect
{
ColorFilter effect;
const CStack * target;
const CSpell * source;
bool persistent;
};
/// Class responsible for handling stacks in battle
/// Handles ordering of stacks animation
/// As well as rendering of stacks, their amount boxes
/// And any other effect applied to stacks
class BattleStacksController
{
BattleInterface & owner;
std::shared_ptr<IImage> amountNormal;
std::shared_ptr<IImage> amountNegative;
std::shared_ptr<IImage> amountPositive;
std::shared_ptr<IImage> amountEffNeutral;
/// currently displayed animations <anim, initialized>
std::vector<BattleAnimation *> currentAnimations;
/// currently active color effects on stacks, in order of their addition (which corresponds to their apply order)
std::vector<BattleStackFilterEffect> stackFilterEffects;
/// animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
std::map<int32_t, std::shared_ptr<CreatureAnimation>> stackAnimation;
/// <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
std::map<int, bool> stackFacingRight;
/// Stacks have amount box hidden due to ongoing animations
std::set<int> stackAmountBoxHidden;
/// currently active stack; nullptr - no one
const CStack *activeStack;
/// stacks or their battle queue images below mouse pointer (multiple stacks possible while spellcasting), used for border animation
std::vector<const CStack *> mouseHoveredStacks;
///when animation is playing, we should wait till the end to make the next stack active; nullptr of none
const CStack *stackToActivate;
/// for giving IDs for animations
ui32 animIDhelper;
bool stackNeedsAmountBox(const CStack * stack) const;
void showStackAmountBox(Canvas & canvas, const CStack * stack);
BattleHex getStackCurrentPosition(const CStack * stack) const;
std::shared_ptr<IImage> getStackAmountBox(const CStack * stack);
void removeExpiredColorFilters();
void initializeBattleAnimations();
void tickFrameBattleAnimations(uint32_t msPassed);
void updateBattleAnimations(uint32_t msPassed);
std::vector<const CStack *> selectHoveredStacks();
bool shouldAttackFacingRight(const CStack * attacker, const CStack * defender);
public:
BattleStacksController(BattleInterface & owner);
bool shouldRotate(const CStack * stack, const BattleHex & oldPos, const BattleHex & nextHex) const;
bool facingRight(const CStack * stack) const;
void stackReset(const CStack * stack);
void stackAdded(const CStack * stack, bool instant); //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); //stack with id number moved to destHex
void stackTeleported(const CStack *stack, const BattleHexArray & destHex, int distance); //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 & info); //called when stack with id ID is attacking something on hex dest
void startAction(const BattleAction & action);
void endAction(const BattleAction & action);
void deactivateStack(); //copy activeStack to stackToActivate, then set activeStack to nullptr to temporary disable current stack
void activateStack(); //copy stackToActivate to activeStack to enable controls of the stack
void setActiveStack(const CStack *stack);
void showAliveStack(Canvas & canvas, const CStack * stack);
void showStack(Canvas & canvas, const CStack * stack);
void updateHoveredStacks();
void collectRenderableObjects(BattleRenderer & renderer);
/// Adds new color filter effect targeting stack
/// Effect will last as long as stack is affected by specified spell (unless effect is persistent)
/// If effect from same (target, source) already exists, it will be updated
void setStackColorFilter(const ColorFilter & effect, const CStack * target, const CSpell *source, bool persistent);
void addNewAnim(BattleAnimation *anim); //adds new anim to pendingAnims
const CStack* getActiveStack() const;
const std::vector<uint32_t> getHoveredStacksUnitIds() const;
void tick(uint32_t msPassed);
/// returns position of animation needed to place stack in specific hex
Point getStackPositionAtHex(const BattleHex & hexNum, const CStack * creature) const;
friend class BattleAnimation; // for exposing pendingAnims/creAnims/creDir to animations
};
|