mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
Merge pull request #1487 from IvanSavenko/battle_actions_refactoring
Battle actions refactoring
This commit is contained in:
File diff suppressed because it is too large
Load Diff
@@ -14,6 +14,10 @@
|
|||||||
VCMI_LIB_NAMESPACE_BEGIN
|
VCMI_LIB_NAMESPACE_BEGIN
|
||||||
|
|
||||||
class BattleAction;
|
class BattleAction;
|
||||||
|
namespace spells {
|
||||||
|
class Caster;
|
||||||
|
enum class Mode;
|
||||||
|
}
|
||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
@@ -34,65 +38,87 @@ class BattleActionsController
|
|||||||
/// all actions possible to call at the moment by player
|
/// all actions possible to call at the moment by player
|
||||||
std::vector<PossiblePlayerBattleAction> possibleActions;
|
std::vector<PossiblePlayerBattleAction> possibleActions;
|
||||||
|
|
||||||
/// actions possible to take on hovered hex
|
/// spell for which player's hero is choosing destination
|
||||||
std::vector<PossiblePlayerBattleAction> localActions;
|
std::shared_ptr<BattleAction> heroSpellToCast;
|
||||||
|
|
||||||
/// these actions display message in case of illegal target
|
|
||||||
std::vector<PossiblePlayerBattleAction> illegalActions;
|
|
||||||
|
|
||||||
/// action that will be performed on l-click
|
|
||||||
PossiblePlayerBattleAction currentAction;
|
|
||||||
|
|
||||||
/// last action chosen (and saved) by player
|
|
||||||
PossiblePlayerBattleAction selectedAction;
|
|
||||||
|
|
||||||
/// if there are not possible actions to choose from, this action should be show as "illegal" in UI
|
|
||||||
PossiblePlayerBattleAction illegalAction;
|
|
||||||
|
|
||||||
/// if true, stack currently aims to cats a spell
|
|
||||||
bool creatureCasting;
|
|
||||||
|
|
||||||
/// if true, player is choosing destination for his spell - only for GUI / console
|
|
||||||
bool spellDestSelectMode;
|
|
||||||
|
|
||||||
/// spell for which player is choosing destination
|
|
||||||
std::shared_ptr<BattleAction> spellToCast;
|
|
||||||
|
|
||||||
/// spell for which player is choosing destination, pointer for convenience
|
|
||||||
const CSpell *currentSpell;
|
|
||||||
|
|
||||||
/// cached message that was set by this class in status bar
|
/// cached message that was set by this class in status bar
|
||||||
std::string currentConsoleMsg;
|
std::string currentConsoleMsg;
|
||||||
|
|
||||||
|
/// if true, active stack could possibly cast some target spell
|
||||||
|
const CSpell * creatureSpellToCast;
|
||||||
|
|
||||||
bool isCastingPossibleHere (const CStack *sactive, const CStack *shere, BattleHex myNumber);
|
bool isCastingPossibleHere (const CStack *sactive, const CStack *shere, BattleHex myNumber);
|
||||||
bool canStackMoveHere (const CStack *sactive, BattleHex MyNumber) const; //TODO: move to BattleState / callback
|
bool canStackMoveHere (const CStack *sactive, BattleHex MyNumber) const; //TODO: move to BattleState / callback
|
||||||
std::vector<PossiblePlayerBattleAction> getPossibleActionsForStack (const CStack *stack) const; //called when stack gets its turn
|
std::vector<PossiblePlayerBattleAction> getPossibleActionsForStack (const CStack *stack) const; //called when stack gets its turn
|
||||||
void reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context);
|
void reorderPossibleActionsPriority(const CStack * stack, MouseHoveredHexContext context);
|
||||||
|
|
||||||
|
bool actionIsLegal(PossiblePlayerBattleAction action, BattleHex hoveredHex);
|
||||||
|
|
||||||
|
void actionSetCursor(PossiblePlayerBattleAction action, BattleHex hoveredHex);
|
||||||
|
void actionSetCursorBlocked(PossiblePlayerBattleAction action, BattleHex hoveredHex);
|
||||||
|
|
||||||
|
std::string actionGetStatusMessage(PossiblePlayerBattleAction action, BattleHex hoveredHex);
|
||||||
|
std::string actionGetStatusMessageBlocked(PossiblePlayerBattleAction action, BattleHex hoveredHex);
|
||||||
|
|
||||||
|
void actionRealize(PossiblePlayerBattleAction action, BattleHex hoveredHex);
|
||||||
|
|
||||||
|
PossiblePlayerBattleAction selectAction(BattleHex myNumber);
|
||||||
|
|
||||||
|
const CStack * getStackForHex(BattleHex myNumber) ;
|
||||||
|
|
||||||
|
/// attempts to initialize spellcasting action for stack
|
||||||
|
/// will silently return if stack is not a spellcaster
|
||||||
|
void tryActivateStackSpellcasting(const CStack *casterStack);
|
||||||
|
|
||||||
|
/// returns spell that is currently being cast by hero or nullptr if none
|
||||||
|
const CSpell * getHeroSpellToCast() const;
|
||||||
|
|
||||||
|
/// if current stack is spellcaster, returns spell being cast, or null othervice
|
||||||
|
const CSpell * getStackSpellToCast( ) const;
|
||||||
|
|
||||||
|
/// returns true if current stack is a spellcaster
|
||||||
|
bool isActiveStackSpellcaster() const;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BattleActionsController(BattleInterface & owner);
|
BattleActionsController(BattleInterface & owner);
|
||||||
|
|
||||||
/// initialize list of potential actions for new active stack
|
/// initialize list of potential actions for new active stack
|
||||||
void activateStack();
|
void activateStack();
|
||||||
|
|
||||||
/// initialize potential actions for spells that can be cast by active stack
|
/// returns true if UI is currently in target selection mode
|
||||||
|
bool spellcastingModeActive() const;
|
||||||
|
|
||||||
|
/// returns true if one of the following is true:
|
||||||
|
/// - we are casting spell by hero
|
||||||
|
/// - we are casting spell by creature in targeted mode (F hotkey)
|
||||||
|
/// - current creature is spellcaster and preferred action for current hex is spellcast
|
||||||
|
bool currentActionSpellcasting(BattleHex hoveredHex);
|
||||||
|
|
||||||
|
/// enter targeted spellcasting mode for creature, e.g. via "F" hotkey
|
||||||
void enterCreatureCastingMode();
|
void enterCreatureCastingMode();
|
||||||
|
|
||||||
/// initialize potential actions for selected spell
|
/// initialize hero spellcasting mode, e.g. on selecting spell in spellbook
|
||||||
void castThisSpell(SpellID spellID);
|
void castThisSpell(SpellID spellID);
|
||||||
|
|
||||||
/// ends casting spell (eg. when spell has been cast or canceled)
|
/// ends casting spell (eg. when spell has been cast or canceled)
|
||||||
void endCastingSpell();
|
void endCastingSpell();
|
||||||
|
|
||||||
/// update UI (e.g. status bar/cursor) according to new active hex
|
/// update cursor and status bar according to new active hex
|
||||||
void handleHex(BattleHex myNumber, int eventType);
|
void onHexHovered(BattleHex hoveredHex);
|
||||||
|
|
||||||
/// returns currently selected spell or SpellID::NONE on error
|
/// called when cursor is no longer over battlefield and cursor/battle log should be reset
|
||||||
SpellID selectedSpell() const;
|
void onHoverEnded();
|
||||||
|
|
||||||
|
/// performs action according to selected hex
|
||||||
|
void onHexLeftClicked(BattleHex clickedHex);
|
||||||
|
|
||||||
|
/// performs action according to selected hex
|
||||||
|
void onHexRightClicked(BattleHex clickedHex);
|
||||||
|
|
||||||
|
const spells::Caster * getCurrentSpellcaster() const;
|
||||||
|
const CSpell * getCurrentSpell() const;
|
||||||
|
spells::Mode getCurrentCastMode() const;
|
||||||
|
|
||||||
/// returns true if UI is currently in target selection mode
|
|
||||||
bool spellcastingModeActive() const;
|
|
||||||
|
|
||||||
/// methods to work with array of possible actions, needed to control special creatures abilities
|
/// methods to work with array of possible actions, needed to control special creatures abilities
|
||||||
const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;
|
const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;
|
||||||
void removePossibleAction(PossiblePlayerBattleAction);
|
void removePossibleAction(PossiblePlayerBattleAction);
|
||||||
|
@@ -34,6 +34,8 @@
|
|||||||
#include "../../lib/CStack.h"
|
#include "../../lib/CStack.h"
|
||||||
#include "../../lib/spells/ISpellMechanics.h"
|
#include "../../lib/spells/ISpellMechanics.h"
|
||||||
|
|
||||||
|
#include <SDL_events.h>
|
||||||
|
|
||||||
BattleFieldController::BattleFieldController(BattleInterface & owner):
|
BattleFieldController::BattleFieldController(BattleInterface & owner):
|
||||||
owner(owner)
|
owner(owner)
|
||||||
{
|
{
|
||||||
@@ -76,20 +78,11 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
|
|||||||
|
|
||||||
backgroundWithHexes = std::make_unique<Canvas>(Point(background->width(), background->height()));
|
backgroundWithHexes = std::make_unique<Canvas>(Point(background->width(), background->height()));
|
||||||
|
|
||||||
for (int h = 0; h < GameConstants::BFIELD_SIZE; ++h)
|
|
||||||
{
|
|
||||||
auto hex = std::make_shared<ClickableHex>();
|
|
||||||
hex->myNumber = h;
|
|
||||||
hex->pos = hexPositionAbsolute(h);
|
|
||||||
hex->myInterface = &owner;
|
|
||||||
bfield.push_back(hex);
|
|
||||||
}
|
|
||||||
|
|
||||||
auto accessibility = owner.curInt->cb->getAccesibility();
|
auto accessibility = owner.curInt->cb->getAccesibility();
|
||||||
for(int i = 0; i < accessibility.size(); i++)
|
for(int i = 0; i < accessibility.size(); i++)
|
||||||
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
|
stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE);
|
||||||
|
|
||||||
addUsedEvents(MOVE);
|
addUsedEvents(LCLICK | RCLICK | MOVE);
|
||||||
LOCPLINT->cingconsole->pos = this->pos;
|
LOCPLINT->cingconsole->pos = this->pos;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -107,11 +100,38 @@ void BattleFieldController::createHeroes()
|
|||||||
|
|
||||||
void BattleFieldController::mouseMoved(const SDL_MouseMotionEvent &event)
|
void BattleFieldController::mouseMoved(const SDL_MouseMotionEvent &event)
|
||||||
{
|
{
|
||||||
BattleHex selectedHex = getHoveredHex();
|
if (!pos.isInside(event.x, event.y))
|
||||||
|
{
|
||||||
|
owner.actionsController->onHoverEnded();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
owner.actionsController->handleHex(selectedHex, MOVE);
|
BattleHex selectedHex = getHoveredHex();
|
||||||
|
owner.actionsController->onHexHovered(selectedHex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleFieldController::clickLeft(tribool down, bool previousState)
|
||||||
|
{
|
||||||
|
if(!down)
|
||||||
|
{
|
||||||
|
BattleHex selectedHex = getHoveredHex();
|
||||||
|
|
||||||
|
if (selectedHex != BattleHex::INVALID)
|
||||||
|
owner.actionsController->onHexLeftClicked(selectedHex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleFieldController::clickRight(tribool down, bool previousState)
|
||||||
|
{
|
||||||
|
if(down)
|
||||||
|
{
|
||||||
|
BattleHex selectedHex = getHoveredHex();
|
||||||
|
|
||||||
|
if (selectedHex != BattleHex::INVALID)
|
||||||
|
owner.actionsController->onHexRightClicked(selectedHex);
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void BattleFieldController::renderBattlefield(Canvas & canvas)
|
void BattleFieldController::renderBattlefield(Canvas & canvas)
|
||||||
{
|
{
|
||||||
@@ -233,19 +253,9 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
|
|||||||
const spells::Caster *caster = nullptr;
|
const spells::Caster *caster = nullptr;
|
||||||
const CSpell *spell = nullptr;
|
const CSpell *spell = nullptr;
|
||||||
|
|
||||||
spells::Mode mode = spells::Mode::HERO;
|
spells::Mode mode = owner.actionsController->getCurrentCastMode();
|
||||||
|
spell = owner.actionsController->getCurrentSpell();
|
||||||
if(owner.actionsController->spellcastingModeActive())//hero casts spell
|
caster = owner.actionsController->getCurrentSpellcaster();
|
||||||
{
|
|
||||||
spell = owner.actionsController->selectedSpell().toSpell();
|
|
||||||
caster = owner.getActiveHero();
|
|
||||||
}
|
|
||||||
else if(owner.stacksController->activeStackSpellToCast() != SpellID::NONE)//stack casts spell
|
|
||||||
{
|
|
||||||
spell = SpellID(owner.stacksController->activeStackSpellToCast()).toSpell();
|
|
||||||
caster = owner.stacksController->getActiveStack();
|
|
||||||
mode = spells::Mode::CREATURE_ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(caster && spell) //when casting spell
|
if(caster && spell) //when casting spell
|
||||||
{
|
{
|
||||||
@@ -310,7 +320,10 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
|||||||
std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
|
std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
|
||||||
std::set<BattleHex> hoveredMove = getHighlightedHexesMovementTarget();
|
std::set<BattleHex> hoveredMove = getHighlightedHexesMovementTarget();
|
||||||
|
|
||||||
auto const & hoveredMouse = owner.actionsController->spellcastingModeActive() ? hoveredSpell : hoveredMove;
|
if (getHoveredHex() == BattleHex::INVALID)
|
||||||
|
return;
|
||||||
|
|
||||||
|
auto const & hoveredMouse = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpell : hoveredMove;
|
||||||
|
|
||||||
for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
|
for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
|
||||||
{
|
{
|
||||||
@@ -355,9 +368,31 @@ bool BattleFieldController::isPixelInHex(Point const & position)
|
|||||||
|
|
||||||
BattleHex BattleFieldController::getHoveredHex()
|
BattleHex BattleFieldController::getHoveredHex()
|
||||||
{
|
{
|
||||||
for ( auto const & hex : bfield)
|
Point hoverPos = GH.getCursorPosition();
|
||||||
if (hex->hovered && hex->strictHovered)
|
|
||||||
return hex->myNumber;
|
if (owner.attackingHero)
|
||||||
|
{
|
||||||
|
if (owner.attackingHero->pos.isInside(hoverPos))
|
||||||
|
return BattleHex::HERO_ATTACKER;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (owner.defendingHero)
|
||||||
|
{
|
||||||
|
if (owner.attackingHero->pos.isInside(hoverPos))
|
||||||
|
return BattleHex::HERO_DEFENDER;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
for (int h = 0; h < GameConstants::BFIELD_SIZE; ++h)
|
||||||
|
{
|
||||||
|
Rect hexPosition = hexPositionAbsolute(h);
|
||||||
|
|
||||||
|
if (!hexPosition.isInside(hoverPos))
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (isPixelInHex(hoverPos - hexPosition.topLeft()))
|
||||||
|
return h;
|
||||||
|
}
|
||||||
|
|
||||||
return BattleHex::INVALID;
|
return BattleHex::INVALID;
|
||||||
}
|
}
|
||||||
@@ -520,7 +555,7 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget)
|
|||||||
}
|
}
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return attackTarget.cloneInDirection(BattleHex::LEFT);
|
return BattleHex::INVALID;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -20,7 +20,6 @@ class Point;
|
|||||||
|
|
||||||
VCMI_LIB_NAMESPACE_END
|
VCMI_LIB_NAMESPACE_END
|
||||||
|
|
||||||
class ClickableHex;
|
|
||||||
class BattleHero;
|
class BattleHero;
|
||||||
class Canvas;
|
class Canvas;
|
||||||
class IImage;
|
class IImage;
|
||||||
@@ -50,8 +49,6 @@ class BattleFieldController : public CIntObject
|
|||||||
/// hexes that when in front of a unit cause it's amount box to move back
|
/// hexes that when in front of a unit cause it's amount box to move back
|
||||||
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
|
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
|
||||||
|
|
||||||
std::vector<std::shared_ptr<ClickableHex>> bfield;
|
|
||||||
|
|
||||||
void showHighlightedHex(Canvas & to, BattleHex hex, bool darkBorder);
|
void showHighlightedHex(Canvas & to, BattleHex hex, bool darkBorder);
|
||||||
|
|
||||||
std::set<BattleHex> getHighlightedHexesStackRange();
|
std::set<BattleHex> getHighlightedHexesStackRange();
|
||||||
@@ -66,9 +63,11 @@ class BattleFieldController : public CIntObject
|
|||||||
BattleHex::EDir selectAttackDirection(BattleHex myNumber, const Point & point);
|
BattleHex::EDir selectAttackDirection(BattleHex myNumber, const Point & point);
|
||||||
|
|
||||||
void mouseMoved(const SDL_MouseMotionEvent &event) override;
|
void mouseMoved(const SDL_MouseMotionEvent &event) override;
|
||||||
|
void clickLeft(tribool down, bool previousState) override;
|
||||||
|
void clickRight(tribool down, bool previousState) override;
|
||||||
|
|
||||||
void showAll(SDL_Surface * to) override;
|
void showAll(SDL_Surface * to) override;
|
||||||
void show(SDL_Surface * to) override;
|
void show(SDL_Surface * to) override;
|
||||||
|
|
||||||
public:
|
public:
|
||||||
BattleFieldController(BattleInterface & owner);
|
BattleFieldController(BattleInterface & owner);
|
||||||
|
|
||||||
|
@@ -54,7 +54,6 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
|
|||||||
, attackerInt(att)
|
, attackerInt(att)
|
||||||
, defenderInt(defen)
|
, defenderInt(defen)
|
||||||
, curInt(att)
|
, curInt(att)
|
||||||
, myTurn(false)
|
|
||||||
, moveSoundHander(-1)
|
, moveSoundHander(-1)
|
||||||
{
|
{
|
||||||
for ( auto & event : animationEvents)
|
for ( auto & event : animationEvents)
|
||||||
@@ -267,7 +266,6 @@ void BattleInterface::sendCommand(BattleAction *& command, const CStack * actor)
|
|||||||
if(!tacticsMode)
|
if(!tacticsMode)
|
||||||
{
|
{
|
||||||
logGlobal->trace("Setting command for %s", (actor ? actor->nodeName() : "hero"));
|
logGlobal->trace("Setting command for %s", (actor ? actor->nodeName() : "hero"));
|
||||||
myTurn = false;
|
|
||||||
stacksController->setActiveStack(nullptr);
|
stacksController->setActiveStack(nullptr);
|
||||||
givenCommand.setn(command);
|
givenCommand.setn(command);
|
||||||
}
|
}
|
||||||
@@ -278,6 +276,7 @@ void BattleInterface::sendCommand(BattleAction *& command, const CStack * actor)
|
|||||||
stacksController->setActiveStack(nullptr);
|
stacksController->setActiveStack(nullptr);
|
||||||
//next stack will be activated when action ends
|
//next stack will be activated when action ends
|
||||||
}
|
}
|
||||||
|
CCS->curh->set(Cursor::Combat::POINTER);
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGHeroInstance * BattleInterface::getActiveHero()
|
const CGHeroInstance * BattleInterface::getActiveHero()
|
||||||
@@ -553,7 +552,6 @@ void BattleInterface::activateStack()
|
|||||||
if(!s)
|
if(!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
myTurn = true;
|
|
||||||
windowObject->updateQueue();
|
windowObject->updateQueue();
|
||||||
windowObject->blockUI(false);
|
windowObject->blockUI(false);
|
||||||
fieldController->redrawBackgroundWithHexes();
|
fieldController->redrawBackgroundWithHexes();
|
||||||
@@ -561,6 +559,11 @@ void BattleInterface::activateStack()
|
|||||||
GH.fakeMouseMove();
|
GH.fakeMouseMove();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
bool BattleInterface::makingTurn() const
|
||||||
|
{
|
||||||
|
return stacksController->getActiveStack() != nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
void BattleInterface::endAction(const BattleAction* action)
|
void BattleInterface::endAction(const BattleAction* action)
|
||||||
{
|
{
|
||||||
const CStack *stack = curInt->cb->battleGetStackByID(action->stackNumber);
|
const CStack *stack = curInt->cb->battleGetStackByID(action->stackNumber);
|
||||||
|
@@ -37,7 +37,6 @@ class Canvas;
|
|||||||
class BattleResultWindow;
|
class BattleResultWindow;
|
||||||
class StackQueue;
|
class StackQueue;
|
||||||
class CPlayerInterface;
|
class CPlayerInterface;
|
||||||
class ClickableHex;
|
|
||||||
class CAnimation;
|
class CAnimation;
|
||||||
struct BattleEffect;
|
struct BattleEffect;
|
||||||
class IImage;
|
class IImage;
|
||||||
@@ -146,7 +145,8 @@ public:
|
|||||||
|
|
||||||
static CondSh<BattleAction *> givenCommand; //data != nullptr if we have i.e. moved current unit
|
static CondSh<BattleAction *> givenCommand; //data != nullptr if we have i.e. moved current unit
|
||||||
|
|
||||||
bool myTurn; //if true, interface is active (commands can be ordered)
|
bool makingTurn() const;
|
||||||
|
|
||||||
int moveSoundHander; // sound handler used when moving a unit
|
int moveSoundHander; // sound handler used when moving a unit
|
||||||
|
|
||||||
BattleInterface(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(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);
|
||||||
|
@@ -30,7 +30,6 @@
|
|||||||
#include "../widgets/Images.h"
|
#include "../widgets/Images.h"
|
||||||
#include "../widgets/TextControls.h"
|
#include "../widgets/TextControls.h"
|
||||||
#include "../windows/CMessage.h"
|
#include "../windows/CMessage.h"
|
||||||
#include "../windows/CCreatureWindow.h"
|
|
||||||
#include "../windows/CSpellWindow.h"
|
#include "../windows/CSpellWindow.h"
|
||||||
#include "../render/CAnimation.h"
|
#include "../render/CAnimation.h"
|
||||||
#include "../adventureMap/CInGameConsole.h"
|
#include "../adventureMap/CInGameConsole.h"
|
||||||
@@ -274,50 +273,29 @@ void BattleHero::setPhase(EHeroAnimType newPhase)
|
|||||||
nextPhase = EHeroAnimType::HOLDING;
|
nextPhase = EHeroAnimType::HOLDING;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleHero::hover(bool on)
|
void BattleHero::heroLeftClicked()
|
||||||
{
|
|
||||||
//TODO: BROKEN CODE
|
|
||||||
if (on)
|
|
||||||
CCS->curh->set(Cursor::Combat::HERO);
|
|
||||||
else
|
|
||||||
CCS->curh->set(Cursor::Combat::POINTER);
|
|
||||||
}
|
|
||||||
|
|
||||||
void BattleHero::clickLeft(tribool down, bool previousState)
|
|
||||||
{
|
{
|
||||||
if(owner.actionsController->spellcastingModeActive()) //we are casting a spell
|
if(owner.actionsController->spellcastingModeActive()) //we are casting a spell
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(boost::logic::indeterminate(down))
|
if(!hero || !owner.makingTurn())
|
||||||
return;
|
|
||||||
|
|
||||||
if(!hero || down || !owner.myTurn)
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(owner.getCurrentPlayerInterface()->cb->battleCanCastSpell(hero, spells::Mode::HERO) == ESpellCastProblem::OK) //check conditions
|
if(owner.getCurrentPlayerInterface()->cb->battleCanCastSpell(hero, spells::Mode::HERO) == ESpellCastProblem::OK) //check conditions
|
||||||
{
|
{
|
||||||
BattleHex hoveredHex = owner.fieldController->getHoveredHex();
|
|
||||||
//do nothing when any hex is hovered - hero's animation overlaps battlefield
|
|
||||||
if ( hoveredHex != BattleHex::INVALID )
|
|
||||||
return;
|
|
||||||
|
|
||||||
CCS->curh->set(Cursor::Map::POINTER);
|
CCS->curh->set(Cursor::Map::POINTER);
|
||||||
|
|
||||||
GH.pushIntT<CSpellWindow>(hero, owner.getCurrentPlayerInterface());
|
GH.pushIntT<CSpellWindow>(hero, owner.getCurrentPlayerInterface());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleHero::clickRight(tribool down, bool previousState)
|
void BattleHero::heroRightClicked()
|
||||||
{
|
{
|
||||||
if(boost::logic::indeterminate(down))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Point windowPosition;
|
Point windowPosition;
|
||||||
windowPosition.x = (!defender) ? owner.fieldController->pos.left() + 1 : owner.fieldController->pos.right() - 79;
|
windowPosition.x = (!defender) ? owner.fieldController->pos.left() + 1 : owner.fieldController->pos.right() - 79;
|
||||||
windowPosition.y = owner.fieldController->pos.y + 135;
|
windowPosition.y = owner.fieldController->pos.y + 135;
|
||||||
|
|
||||||
InfoAboutHero targetHero;
|
InfoAboutHero targetHero;
|
||||||
if(down && (owner.myTurn || settings["session"]["spectate"].Bool()))
|
if(owner.makingTurn() || settings["session"]["spectate"].Bool())
|
||||||
{
|
{
|
||||||
auto h = defender ? owner.defendingHeroInstance : owner.attackingHeroInstance;
|
auto h = defender ? owner.defendingHeroInstance : owner.attackingHeroInstance;
|
||||||
targetHero.initFromHero(h, InfoAboutHero::EInfoLevel::INBATTLE);
|
targetHero.initFromHero(h, InfoAboutHero::EInfoLevel::INBATTLE);
|
||||||
@@ -374,8 +352,6 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
|
|||||||
flagAnimation->preload();
|
flagAnimation->preload();
|
||||||
flagAnimation->playerColored(hero->tempOwner);
|
flagAnimation->playerColored(hero->tempOwner);
|
||||||
|
|
||||||
addUsedEvents(LCLICK | RCLICK | HOVER);
|
|
||||||
|
|
||||||
switchToNextPhase();
|
switchToNextPhase();
|
||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
@@ -681,68 +657,6 @@ void BattleResultWindow::bExitf()
|
|||||||
CCS->videoh->close();
|
CCS->videoh->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ClickableHex::hover(bool on)
|
|
||||||
{
|
|
||||||
hovered = on;
|
|
||||||
//Hoverable::hover(on);
|
|
||||||
if(!on && setAlterText)
|
|
||||||
{
|
|
||||||
GH.statusbar->clear();
|
|
||||||
setAlterText = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
ClickableHex::ClickableHex() : setAlterText(false), myNumber(-1), strictHovered(false), myInterface(nullptr)
|
|
||||||
{
|
|
||||||
addUsedEvents(LCLICK | RCLICK | HOVER | MOVE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClickableHex::mouseMoved(const SDL_MouseMotionEvent &sEvent)
|
|
||||||
{
|
|
||||||
strictHovered = myInterface->fieldController->isPixelInHex(Point(sEvent.x-pos.x, sEvent.y-pos.y));
|
|
||||||
|
|
||||||
if(hovered && strictHovered) //print attacked creature to console
|
|
||||||
{
|
|
||||||
const CStack * attackedStack = myInterface->getCurrentPlayerInterface()->cb->battleGetStackByPos(myNumber);
|
|
||||||
if( attackedStack != nullptr &&
|
|
||||||
attackedStack->owner != myInterface->getCurrentPlayerInterface()->playerID &&
|
|
||||||
attackedStack->alive())
|
|
||||||
{
|
|
||||||
MetaString text;
|
|
||||||
text.addTxt(MetaString::GENERAL_TXT, 220);
|
|
||||||
attackedStack->addNameReplacement(text);
|
|
||||||
GH.statusbar->write(text.toString());
|
|
||||||
setAlterText = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if(setAlterText)
|
|
||||||
{
|
|
||||||
GH.statusbar->clear();
|
|
||||||
setAlterText = false;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClickableHex::clickLeft(tribool down, bool previousState)
|
|
||||||
{
|
|
||||||
if(!down && hovered && strictHovered) //we've been really clicked!
|
|
||||||
{
|
|
||||||
myInterface->actionsController->handleHex(myNumber, LCLICK);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void ClickableHex::clickRight(tribool down, bool previousState)
|
|
||||||
{
|
|
||||||
const CStack * myst = myInterface->getCurrentPlayerInterface()->cb->battleGetStackByPos(myNumber); //stack info
|
|
||||||
if(hovered && strictHovered && myst!=nullptr)
|
|
||||||
{
|
|
||||||
if(!myst->alive()) return;
|
|
||||||
if(down)
|
|
||||||
{
|
|
||||||
GH.pushIntT<CStackWindow>(myst, true);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
StackQueue::StackQueue(bool Embedded, BattleInterface & owner)
|
StackQueue::StackQueue(bool Embedded, BattleInterface & owner)
|
||||||
: embedded(Embedded),
|
: embedded(Embedded),
|
||||||
owner(owner)
|
owner(owner)
|
||||||
|
@@ -122,9 +122,9 @@ public:
|
|||||||
void pause();
|
void pause();
|
||||||
void play();
|
void play();
|
||||||
|
|
||||||
void hover(bool on) override;
|
void heroLeftClicked();
|
||||||
void clickLeft(tribool down, bool previousState) override; //call-in
|
void heroRightClicked();
|
||||||
void clickRight(tribool down, bool previousState) override; //call-in
|
|
||||||
BattleHero(const BattleInterface & owner, const CGHeroInstance * hero, bool defender);
|
BattleHero(const BattleInterface & owner, const CGHeroInstance * hero, bool defender);
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -172,24 +172,6 @@ public:
|
|||||||
void show(SDL_Surface * to = 0) override;
|
void show(SDL_Surface * to = 0) override;
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Class which stands for a single hex field on a battlefield
|
|
||||||
class ClickableHex : public CIntObject
|
|
||||||
{
|
|
||||||
private:
|
|
||||||
bool setAlterText; //if true, this hex has set alternative text in console and will clean it
|
|
||||||
public:
|
|
||||||
ui32 myNumber; //number of hex in commonly used format
|
|
||||||
bool strictHovered; //for determining if hex is hovered by mouse (this is different problem than hex's graphic hovering)
|
|
||||||
BattleInterface * myInterface; //interface that owns me
|
|
||||||
|
|
||||||
//for user interactions
|
|
||||||
void hover (bool on) override;
|
|
||||||
void mouseMoved (const SDL_MouseMotionEvent &sEvent) override;
|
|
||||||
void clickLeft(tribool down, bool previousState) override;
|
|
||||||
void clickRight(tribool down, bool previousState) override;
|
|
||||||
ClickableHex();
|
|
||||||
};
|
|
||||||
|
|
||||||
/// Shows the stack queue
|
/// Shows the stack queue
|
||||||
class StackQueue : public CIntObject
|
class StackQueue : public CIntObject
|
||||||
{
|
{
|
||||||
|
@@ -73,8 +73,6 @@ BattleStacksController::BattleStacksController(BattleInterface & owner):
|
|||||||
activeStack(nullptr),
|
activeStack(nullptr),
|
||||||
stackToActivate(nullptr),
|
stackToActivate(nullptr),
|
||||||
selectedStack(nullptr),
|
selectedStack(nullptr),
|
||||||
stackCanCastSpell(false),
|
|
||||||
creatureSpellToCast(uint32_t(-1)),
|
|
||||||
animIDhelper(0)
|
animIDhelper(0)
|
||||||
{
|
{
|
||||||
//preparing graphics for displaying amounts of creatures
|
//preparing graphics for displaying amounts of creatures
|
||||||
@@ -738,25 +736,6 @@ void BattleStacksController::activateStack()
|
|||||||
const CStack * s = getActiveStack();
|
const CStack * s = getActiveStack();
|
||||||
if(!s)
|
if(!s)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
//set casting flag to true if creature can use it to not check it every time
|
|
||||||
const auto spellcaster = s->getBonusLocalFirst(Selector::type()(Bonus::SPELLCASTER));
|
|
||||||
const auto randomSpellcaster = s->getBonusLocalFirst(Selector::type()(Bonus::RANDOM_SPELLCASTER));
|
|
||||||
if(s->canCast() && (spellcaster || randomSpellcaster))
|
|
||||||
{
|
|
||||||
stackCanCastSpell = true;
|
|
||||||
if(randomSpellcaster)
|
|
||||||
creatureSpellToCast = -1; //spell will be set later on cast
|
|
||||||
else
|
|
||||||
creatureSpellToCast = owner.curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), s, CBattleInfoCallback::RANDOM_AIMED); //faerie dragon can cast only one spell until their next move
|
|
||||||
//TODO: what if creature can cast BOTH random genie spell and aimed spell?
|
|
||||||
//TODO: faerie dragon type spell should be selected by server
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
stackCanCastSpell = false;
|
|
||||||
creatureSpellToCast = -1;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleStacksController::setSelectedStack(const CStack *stack)
|
void BattleStacksController::setSelectedStack(const CStack *stack)
|
||||||
@@ -779,18 +758,6 @@ bool BattleStacksController::facingRight(const CStack * stack) const
|
|||||||
return stackFacingRight.at(stack->ID);
|
return stackFacingRight.at(stack->ID);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BattleStacksController::activeStackSpellcaster()
|
|
||||||
{
|
|
||||||
return stackCanCastSpell;
|
|
||||||
}
|
|
||||||
|
|
||||||
SpellID BattleStacksController::activeStackSpellToCast()
|
|
||||||
{
|
|
||||||
if (!stackCanCastSpell)
|
|
||||||
return SpellID::NONE;
|
|
||||||
return SpellID(creatureSpellToCast);
|
|
||||||
}
|
|
||||||
|
|
||||||
Point BattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CStack * stack) const
|
Point BattleStacksController::getStackPositionAtHex(BattleHex hexNum, const CStack * stack) const
|
||||||
{
|
{
|
||||||
Point ret(-500, -500); //returned value
|
Point ret(-500, -500); //returned value
|
||||||
@@ -910,21 +877,11 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
|
|||||||
const spells::Caster *caster = nullptr;
|
const spells::Caster *caster = nullptr;
|
||||||
const CSpell *spell = nullptr;
|
const CSpell *spell = nullptr;
|
||||||
|
|
||||||
spells::Mode mode = spells::Mode::HERO;
|
spells::Mode mode = owner.actionsController->getCurrentCastMode();
|
||||||
|
spell = owner.actionsController->getCurrentSpell();
|
||||||
|
caster = owner.actionsController->getCurrentSpellcaster();
|
||||||
|
|
||||||
if(owner.actionsController->spellcastingModeActive())//hero casts spell
|
if(caster && spell && owner.actionsController->currentActionSpellcasting(hoveredHex) ) //when casting spell
|
||||||
{
|
|
||||||
spell = owner.actionsController->selectedSpell().toSpell();
|
|
||||||
caster = owner.getActiveHero();
|
|
||||||
}
|
|
||||||
else if(owner.stacksController->activeStackSpellToCast() != SpellID::NONE)//stack casts spell
|
|
||||||
{
|
|
||||||
spell = SpellID(owner.stacksController->activeStackSpellToCast()).toSpell();
|
|
||||||
caster = owner.stacksController->getActiveStack();
|
|
||||||
mode = spells::Mode::CREATURE_ACTIVE;
|
|
||||||
}
|
|
||||||
|
|
||||||
if(caster && spell) //when casting spell
|
|
||||||
{
|
{
|
||||||
spells::Target target;
|
spells::Target target;
|
||||||
target.emplace_back(hoveredHex);
|
target.emplace_back(hoveredHex);
|
||||||
|
@@ -79,10 +79,6 @@ class BattleStacksController
|
|||||||
/// stack that was selected for multi-target spells - Teleport / Sacrifice
|
/// stack that was selected for multi-target spells - Teleport / Sacrifice
|
||||||
const CStack *selectedStack;
|
const CStack *selectedStack;
|
||||||
|
|
||||||
/// if true, active stack could possibly cast some target spell
|
|
||||||
bool stackCanCastSpell;
|
|
||||||
si32 creatureSpellToCast;
|
|
||||||
|
|
||||||
/// for giving IDs for animations
|
/// for giving IDs for animations
|
||||||
ui32 animIDhelper;
|
ui32 animIDhelper;
|
||||||
|
|
||||||
@@ -123,9 +119,6 @@ public:
|
|||||||
void startAction(const BattleAction* action);
|
void startAction(const BattleAction* action);
|
||||||
void endAction(const BattleAction* action);
|
void endAction(const BattleAction* action);
|
||||||
|
|
||||||
bool activeStackSpellcaster();
|
|
||||||
SpellID activeStackSpellToCast();
|
|
||||||
|
|
||||||
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
|
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
|
||||||
|
|
||||||
void setActiveStack(const CStack *stack);
|
void setActiveStack(const CStack *stack);
|
||||||
|
@@ -391,7 +391,7 @@ void BattleWindow::bSpellf()
|
|||||||
if (owner.actionsController->spellcastingModeActive())
|
if (owner.actionsController->spellcastingModeActive())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (!owner.myTurn)
|
if (!owner.makingTurn())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
auto myHero = owner.currentHero();
|
auto myHero = owner.currentHero();
|
||||||
|
@@ -78,10 +78,7 @@ float AnimationControls::getCreatureAnimationSpeed(const CCreature * creature, c
|
|||||||
return baseSpeed;
|
return baseSpeed;
|
||||||
|
|
||||||
case ECreatureAnimType::HOLDING:
|
case ECreatureAnimType::HOLDING:
|
||||||
if ( creature->animation.idleAnimationTime > 0.01)
|
return creature->animation.idleAnimationTime;
|
||||||
return speed / creature->animation.idleAnimationTime;
|
|
||||||
else
|
|
||||||
return 0.f; // this animation is disabled for current creature
|
|
||||||
|
|
||||||
case ECreatureAnimType::SHOOT_UP:
|
case ECreatureAnimType::SHOOT_UP:
|
||||||
case ECreatureAnimType::SHOOT_FRONT:
|
case ECreatureAnimType::SHOOT_FRONT:
|
||||||
|
@@ -39,6 +39,10 @@ struct DLL_LINKAGE BattleHex //TODO: decide if this should be changed to class f
|
|||||||
static const si16 CASTLE_BOTTOM_TOWER = -3;
|
static const si16 CASTLE_BOTTOM_TOWER = -3;
|
||||||
static const si16 CASTLE_UPPER_TOWER = -4;
|
static const si16 CASTLE_UPPER_TOWER = -4;
|
||||||
|
|
||||||
|
// hexes for interaction with heroes
|
||||||
|
static const si16 HERO_ATTACKER = 0;
|
||||||
|
static const si16 HERO_DEFENDER = GameConstants::BFIELD_WIDTH - 1;
|
||||||
|
|
||||||
// helpers for rendering
|
// helpers for rendering
|
||||||
static const si16 HEX_BEFORE_ALL = std::numeric_limits<si16>::min();
|
static const si16 HEX_BEFORE_ALL = std::numeric_limits<si16>::min();
|
||||||
static const si16 HEX_AFTER_ALL = std::numeric_limits<si16>::max();
|
static const si16 HEX_AFTER_ALL = std::numeric_limits<si16>::max();
|
||||||
|
@@ -44,13 +44,28 @@ struct DLL_LINKAGE AttackableTiles
|
|||||||
|
|
||||||
enum class PossiblePlayerBattleAction // actions performed at l-click
|
enum class PossiblePlayerBattleAction // actions performed at l-click
|
||||||
{
|
{
|
||||||
INVALID = -1, CREATURE_INFO,
|
INVALID = -1,
|
||||||
MOVE_TACTICS, CHOOSE_TACTICS_STACK,
|
CREATURE_INFO,
|
||||||
MOVE_STACK, ATTACK, WALK_AND_ATTACK, ATTACK_AND_RETURN, SHOOT, //OPEN_GATE, //we can open castle gate during siege
|
HERO_INFO,
|
||||||
NO_LOCATION, ANY_LOCATION, OBSTACLE, TELEPORT, SACRIFICE, RANDOM_GENIE_SPELL,
|
MOVE_TACTICS,
|
||||||
FREE_LOCATION, //used with Force Field and Fire Wall - all tiles affected by spell must be free
|
CHOOSE_TACTICS_STACK,
|
||||||
CATAPULT, HEAL,
|
|
||||||
AIMED_SPELL_CREATURE
|
MOVE_STACK,
|
||||||
|
ATTACK,
|
||||||
|
WALK_AND_ATTACK,
|
||||||
|
ATTACK_AND_RETURN,
|
||||||
|
SHOOT,
|
||||||
|
CATAPULT,
|
||||||
|
HEAL,
|
||||||
|
|
||||||
|
NO_LOCATION, // massive spells that affect every possible target, automatic casts
|
||||||
|
ANY_LOCATION,
|
||||||
|
OBSTACLE,
|
||||||
|
TELEPORT,
|
||||||
|
SACRIFICE,
|
||||||
|
RANDOM_GENIE_SPELL, // random spell on a friendly creature
|
||||||
|
FREE_LOCATION, // used with Force Field and Fire Wall - all tiles affected by spell must be free
|
||||||
|
AIMED_SPELL_CREATURE, // spell targeted at creature
|
||||||
};
|
};
|
||||||
|
|
||||||
struct DLL_LINKAGE BattleClientInterfaceData
|
struct DLL_LINKAGE BattleClientInterfaceData
|
||||||
|
@@ -4448,7 +4448,7 @@ void CGameHandler::updateGateState()
|
|||||||
bool hasForceFieldOnBridge = !battleGetAllObstaclesOnPos(BattleHex(ESiegeHex::GATE_BRIDGE), true).empty();
|
bool hasForceFieldOnBridge = !battleGetAllObstaclesOnPos(BattleHex(ESiegeHex::GATE_BRIDGE), true).empty();
|
||||||
bool hasStackAtGateInner = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_INNER), false) != nullptr;
|
bool hasStackAtGateInner = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_INNER), false) != nullptr;
|
||||||
bool hasStackAtGateOuter = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_OUTER), false) != nullptr;
|
bool hasStackAtGateOuter = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_OUTER), false) != nullptr;
|
||||||
bool hasStackAtGateBridge = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_OUTER), false) != nullptr;
|
bool hasStackAtGateBridge = gs->curB->battleGetStackByPos(BattleHex(ESiegeHex::GATE_BRIDGE), false) != nullptr;
|
||||||
bool hasLongBridge = gs->curB->town->subID == ETownType::FORTRESS;
|
bool hasLongBridge = gs->curB->town->subID == ETownType::FORTRESS;
|
||||||
|
|
||||||
BattleUpdateGateState db;
|
BattleUpdateGateState db;
|
||||||
|
Reference in New Issue
Block a user