1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-02-03 13:01:33 +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;
auto allActions = owner.curInt->cb->getClientActionsForStack(stack, data);
allActions.push_back(PossiblePlayerBattleAction::HERO_INFO);
allActions.push_back(PossiblePlayerBattleAction::CREATURE_INFO);
return std::vector<PossiblePlayerBattleAction>(allActions);
@ -175,8 +176,10 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
return 10; break;
case PossiblePlayerBattleAction::CREATURE_INFO:
return 11; break;
case PossiblePlayerBattleAction::TELEPORT:
case PossiblePlayerBattleAction::HERO_INFO:
return 12; break;
case PossiblePlayerBattleAction::TELEPORT:
return 13; break;
default:
assert(0);
return 200; break;
@ -304,6 +307,9 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
case PossiblePlayerBattleAction::CREATURE_INFO:
CCS->curh->set(Cursor::Combat::QUERY);
return;
case PossiblePlayerBattleAction::HERO_INFO:
CCS->curh->set(Cursor::Combat::HERO);
return;
}
assert(0);
}
@ -394,6 +400,9 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
case PossiblePlayerBattleAction::CREATURE_INFO:
return (boost::format(CGI->generaltexth->allTexts[297]) % targetStack->getName()).str();
case PossiblePlayerBattleAction::HERO_INFO:
return ""; //TODO: "View Hero Stats"
}
assert(0);
return "";
@ -432,6 +441,15 @@ bool BattleActionsController::actionIsLegal(PossiblePlayerBattleAction action, B
case PossiblePlayerBattleAction::CREATURE_INFO:
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_STACK:
if (!(targetStack && targetStack->alive())) //we can walk on dead stacks
@ -562,6 +580,17 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
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::ANY_LOCATION:
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);
currentConsoleMsg.clear();
CCS->curh->set(Cursor::Combat::BLOCKED);
return;
}
@ -684,7 +714,17 @@ void BattleActionsController::onHexHovered(BattleHex hoveredHex)
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)
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
{
return heroSpellToCast != nullptr;;

View File

@ -106,8 +106,14 @@ public:
/// update cursor and status bar according to new active hex
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
void onHexClicked(BattleHex clickedHex);
void onHexLeftClicked(BattleHex clickedHex);
/// performs action according to selected hex
void onHexRightClicked(BattleHex clickedHex);
const spells::Caster * getCurrentSpellcaster() const;
const CSpell * getCurrentSpell() const;

View File

@ -27,7 +27,6 @@
#include "../gui/CGuiHandler.h"
#include "../gui/CursorHandler.h"
#include "../adventureMap/CInGameConsole.h"
#include "../windows/CCreatureWindow.h"
#include "../../CCallback.h"
#include "../../lib/BattleFieldHandler.h"
@ -35,6 +34,8 @@
#include "../../lib/CStack.h"
#include "../../lib/spells/ISpellMechanics.h"
#include <SDL_events.h>
BattleFieldController::BattleFieldController(BattleInterface & owner):
owner(owner)
{
@ -99,8 +100,13 @@ void BattleFieldController::createHeroes()
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);
}
@ -111,7 +117,7 @@ void BattleFieldController::clickLeft(tribool down, bool previousState)
BattleHex selectedHex = getHoveredHex();
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();
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();
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);

View File

@ -273,24 +273,12 @@ void BattleHero::setPhase(EHeroAnimType newPhase)
nextPhase = EHeroAnimType::HOLDING;
}
void BattleHero::hover(bool on)
{
//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)
void BattleHero::heroLeftClicked()
{
if(owner.actionsController->spellcastingModeActive()) //we are casting a spell
return;
if(boost::logic::indeterminate(down))
return;
if(!hero || down || !owner.makingTurn())
if(!hero || !owner.makingTurn())
return;
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;
windowPosition.x = (!defender) ? owner.fieldController->pos.left() + 1 : owner.fieldController->pos.right() - 79;
windowPosition.y = owner.fieldController->pos.y + 135;
InfoAboutHero targetHero;
if(down && (owner.makingTurn() || settings["session"]["spectate"].Bool()))
if(owner.makingTurn() || settings["session"]["spectate"].Bool())
{
auto h = defender ? owner.defendingHeroInstance : owner.attackingHeroInstance;
targetHero.initFromHero(h, InfoAboutHero::EInfoLevel::INBATTLE);
@ -373,8 +358,6 @@ BattleHero::BattleHero(const BattleInterface & owner, const CGHeroInstance * her
flagAnimation->preload();
flagAnimation->playerColored(hero->tempOwner);
addUsedEvents(LCLICK | RCLICK | HOVER);
switchToNextPhase();
play();
}

View File

@ -122,9 +122,9 @@ public:
void pause();
void play();
void hover(bool on) override;
void clickLeft(tribool down, bool previousState) override; //call-in
void clickRight(tribool down, bool previousState) override; //call-in
void heroLeftClicked();
void heroRightClicked();
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_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
static const si16 HEX_BEFORE_ALL = std::numeric_limits<si16>::min();
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,
CREATURE_INFO,
HERO_INFO,
MOVE_TACTICS,
CHOOSE_TACTICS_STACK,