1
0
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:
Ivan Savenko
2023-01-29 17:52:19 +02:00
parent d3c85a19cb
commit 9678296875
7 changed files with 99 additions and 33 deletions

View File

@@ -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;;

View File

@@ -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;

View File

@@ -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);

View File

@@ -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();
} }

View File

@@ -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);
}; };

View File

@@ -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();

View File

@@ -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,