mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Hero interaction is now battle action
This commit is contained in:
@@ -134,6 +134,7 @@ std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActi
|
|||||||
data.tacticsMode = owner.tacticsMode;
|
data.tacticsMode = owner.tacticsMode;
|
||||||
auto allActions = owner.curInt->cb->getClientActionsForStack(stack, data);
|
auto allActions = owner.curInt->cb->getClientActionsForStack(stack, data);
|
||||||
|
|
||||||
|
allActions.push_back(PossiblePlayerBattleAction::HERO_INFO);
|
||||||
allActions.push_back(PossiblePlayerBattleAction::CREATURE_INFO);
|
allActions.push_back(PossiblePlayerBattleAction::CREATURE_INFO);
|
||||||
|
|
||||||
return std::vector<PossiblePlayerBattleAction>(allActions);
|
return std::vector<PossiblePlayerBattleAction>(allActions);
|
||||||
@@ -175,8 +176,10 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
|
|||||||
return 10; break;
|
return 10; break;
|
||||||
case PossiblePlayerBattleAction::CREATURE_INFO:
|
case PossiblePlayerBattleAction::CREATURE_INFO:
|
||||||
return 11; break;
|
return 11; break;
|
||||||
case PossiblePlayerBattleAction::TELEPORT:
|
case PossiblePlayerBattleAction::HERO_INFO:
|
||||||
return 12; break;
|
return 12; break;
|
||||||
|
case PossiblePlayerBattleAction::TELEPORT:
|
||||||
|
return 13; break;
|
||||||
default:
|
default:
|
||||||
assert(0);
|
assert(0);
|
||||||
return 200; break;
|
return 200; break;
|
||||||
@@ -304,6 +307,9 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
|
|||||||
case PossiblePlayerBattleAction::CREATURE_INFO:
|
case PossiblePlayerBattleAction::CREATURE_INFO:
|
||||||
CCS->curh->set(Cursor::Combat::QUERY);
|
CCS->curh->set(Cursor::Combat::QUERY);
|
||||||
return;
|
return;
|
||||||
|
case PossiblePlayerBattleAction::HERO_INFO:
|
||||||
|
CCS->curh->set(Cursor::Combat::HERO);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
}
|
}
|
||||||
@@ -394,6 +400,9 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
|
|||||||
|
|
||||||
case PossiblePlayerBattleAction::CREATURE_INFO:
|
case PossiblePlayerBattleAction::CREATURE_INFO:
|
||||||
return (boost::format(CGI->generaltexth->allTexts[297]) % targetStack->getName()).str();
|
return (boost::format(CGI->generaltexth->allTexts[297]) % targetStack->getName()).str();
|
||||||
|
|
||||||
|
case PossiblePlayerBattleAction::HERO_INFO:
|
||||||
|
return ""; //TODO: "View Hero Stats"
|
||||||
}
|
}
|
||||||
assert(0);
|
assert(0);
|
||||||
return "";
|
return "";
|
||||||
@@ -432,6 +441,15 @@ bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, B
|
|||||||
case PossiblePlayerBattleAction::CREATURE_INFO:
|
case PossiblePlayerBattleAction::CREATURE_INFO:
|
||||||
return (targetStack && targetStackOwned);
|
return (targetStack && targetStackOwned);
|
||||||
|
|
||||||
|
case PossiblePlayerBattleAction::HERO_INFO:
|
||||||
|
if (targetHex == BattleHex::HERO_ATTACKER)
|
||||||
|
return owner.attackingHero != nullptr;
|
||||||
|
|
||||||
|
if (targetHex == BattleHex::HERO_DEFENDER)
|
||||||
|
return owner.defendingHero != nullptr;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
|
||||||
case PossiblePlayerBattleAction::MOVE_TACTICS:
|
case PossiblePlayerBattleAction::MOVE_TACTICS:
|
||||||
case PossiblePlayerBattleAction::MOVE_STACK:
|
case PossiblePlayerBattleAction::MOVE_STACK:
|
||||||
if (!(targetStack && targetStack->alive())) //we can walk on dead stacks
|
if (!(targetStack && targetStack->alive())) //we can walk on dead stacks
|
||||||
@@ -562,6 +580,17 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case PossiblePlayerBattleAction::HERO_INFO:
|
||||||
|
{
|
||||||
|
if (targetHex == BattleHex::HERO_ATTACKER)
|
||||||
|
owner.attackingHero->heroLeftClicked();
|
||||||
|
|
||||||
|
if (targetHex == BattleHex::HERO_DEFENDER)
|
||||||
|
owner.defendingHero->heroLeftClicked();
|
||||||
|
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
|
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
|
||||||
case PossiblePlayerBattleAction::ANY_LOCATION:
|
case PossiblePlayerBattleAction::ANY_LOCATION:
|
||||||
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL: //we assume that teleport / sacrifice will never be available as random spell
|
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL: //we assume that teleport / sacrifice will never be available as random spell
|
||||||
@@ -657,6 +686,7 @@ void BattleActionsController::onHexHovered(BattleHex hoveredHex)
|
|||||||
GH.statusbar->clearIfMatching(currentConsoleMsg);
|
GH.statusbar->clearIfMatching(currentConsoleMsg);
|
||||||
|
|
||||||
currentConsoleMsg.clear();
|
currentConsoleMsg.clear();
|
||||||
|
CCS->curh->set(Cursor::Combat::BLOCKED);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -684,7 +714,17 @@ void BattleActionsController::onHexHovered(BattleHex hoveredHex)
|
|||||||
currentConsoleMsg = newConsoleMsg;
|
currentConsoleMsg = newConsoleMsg;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleActionsController::onHexClicked(BattleHex clickedHex)
|
void BattleActionsController::onHoverEnded()
|
||||||
|
{
|
||||||
|
CCS->curh->set(Cursor::Combat::POINTER);
|
||||||
|
|
||||||
|
if (!currentConsoleMsg.empty())
|
||||||
|
GH.statusbar->clearIfMatching(currentConsoleMsg);
|
||||||
|
|
||||||
|
currentConsoleMsg.clear();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleActionsController::onHexLeftClicked(BattleHex clickedHex)
|
||||||
{
|
{
|
||||||
if (owner.stacksController->getActiveStack() == nullptr)
|
if (owner.stacksController->getActiveStack() == nullptr)
|
||||||
return;
|
return;
|
||||||
@@ -797,6 +837,20 @@ void BattleActionsController::activateStack()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void BattleActionsController::onHexRightClicked(BattleHex clickedHex)
|
||||||
|
{
|
||||||
|
auto selectedStack = owner.curInt->cb->battleGetStackByPos(clickedHex, true);
|
||||||
|
|
||||||
|
if (selectedStack != nullptr)
|
||||||
|
GH.pushIntT<CStackWindow>(selectedStack, true);
|
||||||
|
|
||||||
|
if (clickedHex == BattleHex::HERO_ATTACKER && owner.attackingHero)
|
||||||
|
owner.attackingHero->heroRightClicked();
|
||||||
|
|
||||||
|
if (clickedHex == BattleHex::HERO_DEFENDER && owner.defendingHero)
|
||||||
|
owner.defendingHero->heroRightClicked();
|
||||||
|
}
|
||||||
|
|
||||||
bool BattleActionsController::spellcastingModeActive() const
|
bool BattleActionsController::spellcastingModeActive() const
|
||||||
{
|
{
|
||||||
return heroSpellToCast != nullptr;;
|
return heroSpellToCast != nullptr;;
|
||||||
|
@@ -106,8 +106,14 @@ public:
|
|||||||
/// update cursor and status bar according to new active hex
|
/// update cursor and status bar according to new active hex
|
||||||
void onHexHovered(BattleHex hoveredHex);
|
void onHexHovered(BattleHex hoveredHex);
|
||||||
|
|
||||||
|
/// called when cursor is no longer over battlefield and cursor/battle log should be reset
|
||||||
|
void onHoverEnded();
|
||||||
|
|
||||||
/// performs action according to selected hex
|
/// performs action according to selected hex
|
||||||
void onHexClicked(BattleHex clickedHex);
|
void onHexLeftClicked(BattleHex clickedHex);
|
||||||
|
|
||||||
|
/// performs action according to selected hex
|
||||||
|
void onHexRightClicked(BattleHex clickedHex);
|
||||||
|
|
||||||
const spells::Caster * getCurrentSpellcaster() const;
|
const spells::Caster * getCurrentSpellcaster() const;
|
||||||
const CSpell * getCurrentSpell() const;
|
const CSpell * getCurrentSpell() const;
|
||||||
|
@@ -27,7 +27,6 @@
|
|||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/CursorHandler.h"
|
#include "../gui/CursorHandler.h"
|
||||||
#include "../adventureMap/CInGameConsole.h"
|
#include "../adventureMap/CInGameConsole.h"
|
||||||
#include "../windows/CCreatureWindow.h"
|
|
||||||
|
|
||||||
#include "../../CCallback.h"
|
#include "../../CCallback.h"
|
||||||
#include "../../lib/BattleFieldHandler.h"
|
#include "../../lib/BattleFieldHandler.h"
|
||||||
@@ -35,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)
|
||||||
{
|
{
|
||||||
@@ -99,8 +100,13 @@ 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;
|
||||||
|
}
|
||||||
|
|
||||||
|
BattleHex selectedHex = getHoveredHex();
|
||||||
owner.actionsController->onHexHovered(selectedHex);
|
owner.actionsController->onHexHovered(selectedHex);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -111,7 +117,7 @@ void BattleFieldController::clickLeft(tribool down, bool previousState)
|
|||||||
BattleHex selectedHex = getHoveredHex();
|
BattleHex selectedHex = getHoveredHex();
|
||||||
|
|
||||||
if (selectedHex != BattleHex::INVALID)
|
if (selectedHex != BattleHex::INVALID)
|
||||||
owner.actionsController->onHexClicked(selectedHex);
|
owner.actionsController->onHexLeftClicked(selectedHex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -121,10 +127,9 @@ void BattleFieldController::clickRight(tribool down, bool previousState)
|
|||||||
{
|
{
|
||||||
BattleHex selectedHex = getHoveredHex();
|
BattleHex selectedHex = getHoveredHex();
|
||||||
|
|
||||||
auto selectedStack = owner.curInt->cb->battleGetStackByPos(selectedHex, true);
|
if (selectedHex != BattleHex::INVALID)
|
||||||
|
owner.actionsController->onHexRightClicked(selectedHex);
|
||||||
|
|
||||||
if (selectedStack != nullptr)
|
|
||||||
GH.pushIntT<CStackWindow>(selectedStack, true);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -365,6 +370,19 @@ BattleHex BattleFieldController::getHoveredHex()
|
|||||||
{
|
{
|
||||||
Point hoverPos = GH.getCursorPosition();
|
Point hoverPos = GH.getCursorPosition();
|
||||||
|
|
||||||
|
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)
|
for (int h = 0; h < GameConstants::BFIELD_SIZE; ++h)
|
||||||
{
|
{
|
||||||
Rect hexPosition = hexPositionAbsolute(h);
|
Rect hexPosition = hexPositionAbsolute(h);
|
||||||
|
@@ -273,24 +273,12 @@ 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.makingTurn())
|
|
||||||
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
|
||||||
@@ -306,17 +294,14 @@ void BattleHero::clickLeft(tribool down, bool previousState)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
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.makingTurn() || 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);
|
||||||
@@ -373,8 +358,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();
|
||||||
}
|
}
|
||||||
|
@@ -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);
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -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();
|
||||||
|
@@ -46,6 +46,7 @@ enum class PossiblePlayerBattleAction // actions performed at l-click
|
|||||||
{
|
{
|
||||||
INVALID = -1,
|
INVALID = -1,
|
||||||
CREATURE_INFO,
|
CREATURE_INFO,
|
||||||
|
HERO_INFO,
|
||||||
MOVE_TACTICS,
|
MOVE_TACTICS,
|
||||||
CHOOSE_TACTICS_STACK,
|
CHOOSE_TACTICS_STACK,
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user