Browse Source

Hero interaction is now battle action

Ivan Savenko 2 years ago
parent
commit
9678296875

+ 56 - 2
client/battle/BattleActionsController.cpp

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

+ 7 - 1
client/battle/BattleActionsController.h

@@ -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 onHexLeftClicked(BattleHex clickedHex);
+
 	/// performs action according to selected hex
-	void onHexClicked(BattleHex clickedHex);
+	void onHexRightClicked(BattleHex clickedHex);
 
 	const spells::Caster * getCurrentSpellcaster() const;
 	const CSpell * getCurrentSpell() const;

+ 24 - 6
client/battle/BattleFieldController.cpp

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

+ 4 - 21
client/battle/BattleInterfaceClasses.cpp

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

+ 3 - 3
client/battle/BattleInterfaceClasses.h

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

+ 4 - 0
lib/battle/BattleHex.h

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

+ 1 - 0
lib/battle/CBattleInfoCallback.h

@@ -46,6 +46,7 @@ enum class PossiblePlayerBattleAction // actions performed at l-click
 {
 	INVALID = -1,
 	CREATURE_INFO,
+	HERO_INFO,
 	MOVE_TACTICS,
 	CHOOSE_TACTICS_STACK,