Browse Source

Spellcasters UI now shares handling with hero spellcasting

Ivan Savenko 2 years ago
parent
commit
c3b79c786b

+ 45 - 16
client/battle/BattleActionsController.cpp

@@ -86,7 +86,7 @@ void BattleActionsController::enterCreatureCastingMode()
 	if (vstd::contains(possibleActions, PossiblePlayerBattleAction::NO_LOCATION))
 	{
 		const spells::Caster * caster = owner.stacksController->getActiveStack();
-		const CSpell * spell = getStackSpellToCast(BattleHex::INVALID);
+		const CSpell * spell = getStackSpellToCast();
 
 		spells::Target target;
 		target.emplace_back();
@@ -126,8 +126,8 @@ std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActi
 {
 	BattleClientInterfaceData data; //hard to get rid of these things so for now they're required data to pass
 
-	if (getStackSpellToCast(BattleHex::INVALID))
-		data.creatureSpellToCast = getStackSpellToCast(BattleHex::INVALID)->getId();
+	if (getStackSpellToCast())
+		data.creatureSpellToCast = getStackSpellToCast()->getId();
 	else
 		data.creatureSpellToCast = SpellID::NONE;
 
@@ -175,6 +175,8 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
 			return 10; break;
 		case PossiblePlayerBattleAction::CREATURE_INFO:
 			return 11; break;
+		case PossiblePlayerBattleAction::TELEPORT:
+			return 12; break;
 		default:
 			assert(0);
 			return 200; break;
@@ -223,7 +225,7 @@ const CSpell * BattleActionsController::getHeroSpellToCast( ) const
 	return nullptr;
 }
 
-const CSpell * BattleActionsController::getStackSpellToCast( BattleHex targetHex ) const
+const CSpell * BattleActionsController::getStackSpellToCast( ) const
 {
 	if (isActiveStackSpellcaster())
 		return creatureSpellToCast;
@@ -231,11 +233,11 @@ const CSpell * BattleActionsController::getStackSpellToCast( BattleHex targetHex
 	return nullptr;
 }
 
-const CSpell * BattleActionsController::getAnySpellToCast( BattleHex targetHex ) const
+const CSpell * BattleActionsController::getCurrentSpell( ) const
 {
 	if (getHeroSpellToCast())
 		return getHeroSpellToCast();
-	return getStackSpellToCast(targetHex);
+	return getStackSpellToCast();
 }
 
 const CStack * BattleActionsController::getStackForHex(BattleHex hoveredHex)
@@ -364,10 +366,10 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
 		}
 
 		case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
-			return boost::str(boost::format(CGI->generaltexth->allTexts[27]) % getAnySpellToCast(targetHex)->getNameTranslated() % targetStack->getName()); //Cast %s on %s
+			return boost::str(boost::format(CGI->generaltexth->allTexts[27]) % getCurrentSpell()->getNameTranslated() % targetStack->getName()); //Cast %s on %s
 
 		case PossiblePlayerBattleAction::ANY_LOCATION:
-			return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getAnySpellToCast(targetHex)->getNameTranslated()); //Cast %s
+			return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getCurrentSpell()->getNameTranslated()); //Cast %s
 
 		case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL: //we assume that teleport / sacrifice will never be available as random spell
 			return boost::str(boost::format(CGI->generaltexth->allTexts[301]) % targetStack->getName()); //Cast a spell on %
@@ -382,7 +384,7 @@ std::string BattleActionsController::actionGetStatusMessage(PossiblePlayerBattle
 			return (boost::format(CGI->generaltexth->allTexts[549]) % targetStack->getName()).str(); //sacrifice the %s
 
 		case PossiblePlayerBattleAction::FREE_LOCATION:
-			return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getAnySpellToCast(targetHex)->getNameTranslated()); //Cast %s
+			return boost::str(boost::format(CGI->generaltexth->allTexts[26]) % getCurrentSpell()->getNameTranslated()); //Cast %s
 
 		case PossiblePlayerBattleAction::HEAL:
 			return (boost::format(CGI->generaltexth->allTexts[419]) % targetStack->getName()).str(); //Apply first aid to the %s
@@ -412,7 +414,7 @@ std::string BattleActionsController::actionGetStatusMessageBlocked(PossiblePlaye
 			return CGI->generaltexth->allTexts[543]; //choose army to sacrifice
 			break;
 		case PossiblePlayerBattleAction::FREE_LOCATION:
-			return boost::str(boost::format(CGI->generaltexth->allTexts[181]) % getAnySpellToCast(targetHex)->getNameTranslated()); //No room to place %s here
+			return boost::str(boost::format(CGI->generaltexth->allTexts[181]) % getCurrentSpell()->getNameTranslated()); //No room to place %s here
 			break;
 		default:
 			return "";
@@ -570,25 +572,27 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
 		{
 			if (action == PossiblePlayerBattleAction::AIMED_SPELL_CREATURE )
 			{
-				if (getAnySpellToCast(targetHex)->id == SpellID::SACRIFICE)
+				if (getCurrentSpell()->id == SpellID::SACRIFICE)
 				{
 					heroSpellToCast->aimToHex(targetHex);
 					possibleActions.push_back(PossiblePlayerBattleAction::SACRIFICE);
+					owner.stacksController->setSelectedStack(targetStack);
 					return;
 				}
-				if (getAnySpellToCast(targetHex)->id == SpellID::TELEPORT)
+				if (getCurrentSpell()->id == SpellID::TELEPORT)
 				{
 					heroSpellToCast->aimToUnit(targetStack);
 					possibleActions.push_back(PossiblePlayerBattleAction::TELEPORT);
+					owner.stacksController->setSelectedStack(targetStack);
 					return;
 				}
 			}
 
 			if (!spellcastingModeActive())
 			{
-				if (getStackSpellToCast(targetHex))
+				if (getStackSpellToCast())
 				{
-					owner.giveCommand(EActionType::MONSTER_SPELL, targetHex, getStackSpellToCast(targetHex)->getId());
+					owner.giveCommand(EActionType::MONSTER_SPELL, targetHex, getStackSpellToCast()->getId());
 				}
 				else //unknown random spell
 				{
@@ -703,7 +707,6 @@ void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterS
 	if(casterStack->canCast() && spellcaster)
 	{
 		// faerie dragon can cast only one, randomly selected 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
 		creatureSpellToCast = owner.curInt->cb->battleGetRandomStackSpell(CRandomGenerator::getDefault(), casterStack, CBattleInfoCallback::RANDOM_AIMED).toSpell();
 	}
@@ -715,12 +718,20 @@ const spells::Caster * BattleActionsController::getCurrentSpellcaster() const
 		return owner.getActiveHero();
 	else
 		return owner.stacksController->getActiveStack();
+}
+
+spells::Mode BattleActionsController::getCurrentCastMode() const
+{
+	if (heroSpellToCast)
+		return spells::Mode::HERO;
+	else
+		return spells::Mode::CREATURE_ACTIVE;
 
 }
 
 bool BattleActionsController::isCastingPossibleHere(const CStack *casterStack, const CStack *targetStack, BattleHex targetHex)
 {
-	auto currentSpell = getAnySpellToCast(targetHex);
+	auto currentSpell = getCurrentSpell();
 	assert(currentSpell);
 
 	if (!currentSpell)
@@ -791,6 +802,24 @@ bool BattleActionsController::spellcastingModeActive() const
 	return heroSpellToCast != nullptr;;
 }
 
+bool BattleActionsController::currentActionSpellcasting(BattleHex hoveredHex)
+{
+	if (heroSpellToCast)
+		return true;
+
+	if (!owner.stacksController->getActiveStack())
+		return false;
+
+	auto action = selectAction(hoveredHex);
+
+	return
+		action == PossiblePlayerBattleAction::ANY_LOCATION ||
+		action == PossiblePlayerBattleAction::NO_LOCATION ||
+		action == PossiblePlayerBattleAction::FREE_LOCATION ||
+		action == PossiblePlayerBattleAction::AIMED_SPELL_CREATURE ||
+		action == PossiblePlayerBattleAction::OBSTACLE;
+}
+
 const std::vector<PossiblePlayerBattleAction> & BattleActionsController::getPossibleActions() const
 {
 	return possibleActions;

+ 20 - 11
client/battle/BattleActionsController.h

@@ -16,6 +16,7 @@ VCMI_LIB_NAMESPACE_BEGIN
 class BattleAction;
 namespace spells {
 class Caster;
+enum class Mode;
 }
 
 VCMI_LIB_NAMESPACE_END
@@ -63,13 +64,21 @@ class BattleActionsController
 
 	PossiblePlayerBattleAction selectAction(BattleHex myNumber);
 
-	const CStack * getStackForHex(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);
 
-	const spells::Caster * getCurrentSpellcaster() const;
+	/// 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:
 	BattleActionsController(BattleInterface & owner);
 
@@ -79,6 +88,12 @@ public:
 	/// 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();
 
@@ -94,15 +109,9 @@ public:
 	/// performs action according to selected hex
 	void onHexClicked(BattleHex clickedHex);
 
-	/// 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( BattleHex targetHex ) const;
-	const CSpell * getAnySpellToCast( BattleHex targetHex ) const;
-
-	/// returns true if current stack is a spellcaster
-	bool isActiveStackSpellcaster() const;
+	const spells::Caster * getCurrentSpellcaster() const;
+	const CSpell * getCurrentSpell() const;
+	spells::Mode getCurrentCastMode() const;
 
 	/// methods to work with array of possible actions, needed to control special creatures abilities
 	const std::vector<PossiblePlayerBattleAction> & getPossibleActions() const;

+ 19 - 26
client/battle/BattleFieldController.cpp

@@ -230,25 +230,15 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
 	if(!settings["battle"]["mouseShadow"].Bool())
 		return result;
 
-	const spells::Caster *caster = nullptr;
-	const CSpell *spell = nullptr;
-
-	spells::Mode mode = spells::Mode::HERO;
-
-	if(owner.actionsController->spellcastingModeActive())//hero casts spell
-	{
-		spell = owner.actionsController->getHeroSpellToCast();
-		caster = owner.getActiveHero();
-	}
-	else if(owner.actionsController->getStackSpellToCast(hoveredHex) != nullptr)//stack casts spell
-	{
-		spell = owner.actionsController->getStackSpellToCast(hoveredHex);
-		caster = owner.stacksController->getActiveStack();
-		mode = spells::Mode::CREATURE_ACTIVE;
-	}
-
-	if(caster && spell) //when casting spell
-	{
+	const spells::Caster *caster = nullptr;
+	const CSpell *spell = nullptr;
+
+	spells::Mode mode = owner.actionsController->getCurrentCastMode();
+	spell = owner.actionsController->getCurrentSpell();
+	caster = owner.actionsController->getCurrentSpellcaster();
+
+	if(caster && spell) //when casting spell
+	{
 		// printing shaded hex(es)
 		spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
 		auto shaded = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
@@ -307,13 +297,16 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesMovementTarget()
 void BattleFieldController::showHighlightedHexes(Canvas & canvas)
 {
 	std::set<BattleHex> hoveredStack = getHighlightedHexesStackRange();
-	std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
-	std::set<BattleHex> hoveredMove  = getHighlightedHexesMovementTarget();
-
-	auto const & hoveredMouse = owner.actionsController->spellcastingModeActive() ? hoveredSpell : hoveredMove;
-
-	for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
-	{
+	std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
+	std::set<BattleHex> hoveredMove  = getHighlightedHexesMovementTarget();
+
+	if (getHoveredHex() == BattleHex::INVALID)
+		return;
+
+	auto const & hoveredMouse = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpell : hoveredMove;
+
+	for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
+	{
 		bool stack = hoveredStack.count(b);
 		bool mouse = hoveredMouse.count(b);
 

+ 4 - 14
client/battle/BattleStacksController.cpp

@@ -871,21 +871,11 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
 	const spells::Caster *caster = 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
-	{
-		spell = owner.actionsController->getHeroSpellToCast();
-		caster = owner.getActiveHero();
-	}
-	else if(owner.actionsController->getStackSpellToCast(hoveredHex) != nullptr)//stack casts spell
-	{
-		spell = owner.actionsController->getStackSpellToCast(hoveredHex);
-		caster = owner.stacksController->getActiveStack();
-		mode = spells::Mode::CREATURE_ACTIVE;
-	}
-
-	if(caster && spell) //when casting spell
+	if(caster && spell && owner.actionsController->currentActionSpellcasting(hoveredHex) ) //when casting spell
 	{
 		spells::Target target;
 		target.emplace_back(hoveredHex);