Sfoglia il codice sorgente

Show cursor (including attack direction) when swiping in battle

Ivan Savenko 2 anni fa
parent
commit
ec55ec76b6

+ 72 - 41
client/battle/BattleActionsController.cpp

@@ -160,7 +160,7 @@ void BattleActionsController::enterCreatureCastingMode()
 	if (!isActiveStackSpellcaster())
 		return;
 
-	for (auto const & action : possibleActions)
+	for(const auto & action : possibleActions)
 	{
 		if (action.get() != PossiblePlayerBattleAction::NO_LOCATION)
 			continue;
@@ -203,7 +203,7 @@ std::vector<PossiblePlayerBattleAction> BattleActionsController::getPossibleActi
 {
 	BattleClientInterfaceData data; //hard to get rid of these things so for now they're required data to pass
 
-	for (auto const & spell : creatureSpells)
+	for(const auto & spell : creatureSpells)
 		data.creatureSpellsToCast.push_back(spell->id);
 
 	data.tacticsMode = owner.tacticsMode;
@@ -219,49 +219,62 @@ void BattleActionsController::reorderPossibleActionsPriority(const CStack * stac
 {
 	if(owner.tacticsMode || possibleActions.empty()) return; //this function is not supposed to be called in tactics mode or before getPossibleActionsForStack
 
-	auto assignPriority = [&](PossiblePlayerBattleAction const & item) -> uint8_t //large lambda assigning priority which would have to be part of possibleActions without it
+	auto assignPriority = [&](const PossiblePlayerBattleAction & item
+						  ) -> uint8_t //large lambda assigning priority which would have to be part of possibleActions without it
 	{
 		switch(item.get())
 		{
-		case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
-		case PossiblePlayerBattleAction::ANY_LOCATION:
-		case PossiblePlayerBattleAction::NO_LOCATION:
-		case PossiblePlayerBattleAction::FREE_LOCATION:
-		case PossiblePlayerBattleAction::OBSTACLE:
-			if(!stack->hasBonusOfType(BonusType::NO_SPELLCAST_BY_DEFAULT) && context == MouseHoveredHexContext::OCCUPIED_HEX)
-				return 1;
-			else
-				return 100;//bottom priority
-			break;
-		case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
-			return 2; break;
-		case PossiblePlayerBattleAction::SHOOT:
-			return 4; break;
-		case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
-			return 5; break;
-		case PossiblePlayerBattleAction::ATTACK:
-			return 6; break;
-		case PossiblePlayerBattleAction::WALK_AND_ATTACK:
-			return 7; break;
-		case PossiblePlayerBattleAction::MOVE_STACK:
-			return 8; break;
-		case PossiblePlayerBattleAction::CATAPULT:
-			return 9; break;
-		case PossiblePlayerBattleAction::HEAL:
-			return 10; break;
-		case PossiblePlayerBattleAction::CREATURE_INFO:
-			return 11; break;
-		case PossiblePlayerBattleAction::HERO_INFO:
-			return 12; break;
-		case PossiblePlayerBattleAction::TELEPORT:
-			return 13; break;
-		default:
-			assert(0);
-			return 200; break;
+			case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
+			case PossiblePlayerBattleAction::ANY_LOCATION:
+			case PossiblePlayerBattleAction::NO_LOCATION:
+			case PossiblePlayerBattleAction::FREE_LOCATION:
+			case PossiblePlayerBattleAction::OBSTACLE:
+				if(!stack->hasBonusOfType(BonusType::NO_SPELLCAST_BY_DEFAULT) && context == MouseHoveredHexContext::OCCUPIED_HEX)
+					return 1;
+				else
+					return 100; //bottom priority
+				break;
+			case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
+				return 2;
+				break;
+			case PossiblePlayerBattleAction::SHOOT:
+				return 4;
+				break;
+			case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
+				return 5;
+				break;
+			case PossiblePlayerBattleAction::ATTACK:
+				return 6;
+				break;
+			case PossiblePlayerBattleAction::WALK_AND_ATTACK:
+				return 7;
+				break;
+			case PossiblePlayerBattleAction::MOVE_STACK:
+				return 8;
+				break;
+			case PossiblePlayerBattleAction::CATAPULT:
+				return 9;
+				break;
+			case PossiblePlayerBattleAction::HEAL:
+				return 10;
+				break;
+			case PossiblePlayerBattleAction::CREATURE_INFO:
+				return 11;
+				break;
+			case PossiblePlayerBattleAction::HERO_INFO:
+				return 12;
+				break;
+			case PossiblePlayerBattleAction::TELEPORT:
+				return 13;
+				break;
+			default:
+				assert(0);
+				return 200;
+				break;
 		}
 	};
 
-	auto comparer = [&](PossiblePlayerBattleAction const & lhs, PossiblePlayerBattleAction const & rhs)
+	auto comparer = [&](const PossiblePlayerBattleAction & lhs, const PossiblePlayerBattleAction & rhs)
 	{
 		return assignPriority(lhs) < assignPriority(rhs);
 	};
@@ -358,8 +371,26 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
 		case PossiblePlayerBattleAction::ATTACK:
 		case PossiblePlayerBattleAction::WALK_AND_ATTACK:
 		case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
-			owner.fieldController->setBattleCursor(targetHex);
+		{
+			static const std::map<BattleHex::EDir, Cursor::Combat> sectorCursor = {
+				{BattleHex::TOP_LEFT,     Cursor::Combat::HIT_SOUTHEAST},
+				{BattleHex::TOP_RIGHT,    Cursor::Combat::HIT_SOUTHWEST},
+				{BattleHex::RIGHT,        Cursor::Combat::HIT_WEST     },
+				{BattleHex::BOTTOM_RIGHT, Cursor::Combat::HIT_NORTHWEST},
+				{BattleHex::BOTTOM_LEFT,  Cursor::Combat::HIT_NORTHEAST},
+				{BattleHex::LEFT,         Cursor::Combat::HIT_EAST     },
+				{BattleHex::TOP,          Cursor::Combat::HIT_SOUTH    },
+				{BattleHex::BOTTOM,       Cursor::Combat::HIT_NORTH    }
+			};
+
+			auto direction = owner.fieldController->selectAttackDirection(targetHex);
+
+			assert(sectorCursor.count(direction) > 0);
+			if (sectorCursor.count(direction))
+				CCS->curh->set(sectorCursor.at(direction));
+
 			return;
+		}
 
 		case PossiblePlayerBattleAction::SHOOT:
 			if (owner.curInt->cb->battleHasShootingPenalty(owner.stacksController->getActiveStack(), targetHex))
@@ -856,7 +887,7 @@ void BattleActionsController::tryActivateStackSpellcasting(const CStack *casterS
 
 	TConstBonusListPtr bl = casterStack->getBonuses(Selector::type()(BonusType::SPELLCASTER));
 
-	for (auto const & bonus : *bl)
+	for(const auto & bonus : *bl)
 	{
 		if (bonus->additionalInfo[0] <= 0)
 			creatureSpells.push_back(SpellID(bonus->subtype).toSpell());

+ 15 - 23
client/battle/BattleFieldController.cpp

@@ -22,6 +22,7 @@
 
 #include "../CGameInfo.h"
 #include "../CPlayerInterface.h"
+#include "../render/CAnimation.h"
 #include "../render/Canvas.h"
 #include "../render/IImage.h"
 #include "../renderSDL/SDL_Extensions.h"
@@ -46,6 +47,9 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
 	cellUnitMovementHighlight = IImage::createFromFile("UnitMovementHighlight.PNG", EImageBlitMode::COLORKEY);
 	cellUnitMaxMovementHighlight = IImage::createFromFile("UnitMaxMovementHighlight.PNG", EImageBlitMode::COLORKEY);
 
+	attackCursors = std::make_shared<CAnimation>("CRCOMBAT");
+	attackCursors->preload();
+
 	if(!owner.siegeController)
 	{
 		auto bfieldType = owner.curInt->cb->battleGetBattlefieldType();
@@ -435,27 +439,7 @@ BattleHex BattleFieldController::getHexAtPosition(Point hoverPos)
 	return BattleHex::INVALID;
 }
 
-void BattleFieldController::setBattleCursor(BattleHex myNumber)
-{
-	std::vector<Cursor::Combat> sectorCursor = {
-		Cursor::Combat::HIT_SOUTHEAST,
-		Cursor::Combat::HIT_SOUTHWEST,
-		Cursor::Combat::HIT_WEST,
-		Cursor::Combat::HIT_NORTHWEST,
-		Cursor::Combat::HIT_NORTHEAST,
-		Cursor::Combat::HIT_EAST,
-		Cursor::Combat::HIT_SOUTH,
-		Cursor::Combat::HIT_NORTH,
-	};
-
-	auto direction = static_cast<size_t>(selectAttackDirection(getHoveredHex(), currentAttackOriginPoint));
-
-	assert(direction != -1);
-	if (direction != -1)
-		CCS->curh->set(sectorCursor[direction]);
-}
-
-BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber, const Point & cursorPos)
+BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber)
 {
 	const bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
 	auto neighbours = myNumber.allNeighbouringTiles();
@@ -518,7 +502,7 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber,
 
 	for (size_t i = 0; i < 8; ++i)
 		if (attackAvailability[i])
-			distance2[i] = (testPoint[i].y - cursorPos.y)*(testPoint[i].y - cursorPos.y) + (testPoint[i].x - cursorPos.x)*(testPoint[i].x - cursorPos.x);
+			distance2[i] = (testPoint[i].y - currentAttackOriginPoint.y)*(testPoint[i].y - currentAttackOriginPoint.y) + (testPoint[i].x - currentAttackOriginPoint.x)*(testPoint[i].x - currentAttackOriginPoint.x);
 
 	size_t nearest = -1;
 	for (size_t i = 0; i < 8; ++i)
@@ -531,7 +515,7 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber,
 
 BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget)
 {
-	BattleHex::EDir direction = selectAttackDirection(getHoveredHex(), currentAttackOriginPoint);
+	BattleHex::EDir direction = selectAttackDirection(getHoveredHex());
 
 	const CStack * attacker = owner.stacksController->getActiveStack();
 
@@ -637,6 +621,14 @@ void BattleFieldController::show(Canvas & to)
 	CSDL_Ext::CClipRectGuard guard(to.getInternalSurface(), pos);
 
 	renderBattlefield(to);
+
+	if (isActive() && isPanning() && getHoveredHex() != BattleHex::INVALID)
+	{
+		auto cursorIndex = CCS->curh->get<Cursor::Combat>();
+		auto imageIndex = static_cast<size_t>(cursorIndex);
+
+		canvas.draw(attackCursors->getImage(imageIndex), hexPositionAbsolute(getHoveredHex()).center() - CCS->curh->getPivotOffsetCombat(imageIndex));
+	}
 }
 
 bool BattleFieldController::receiveEvent(const Point & position, int eventType) const

+ 5 - 3
client/battle/BattleFieldController.h

@@ -34,6 +34,8 @@ class BattleFieldController : public CIntObject
 	std::shared_ptr<IImage> cellUnitMaxMovementHighlight;
 	std::shared_ptr<IImage> cellShade;
 
+	std::shared_ptr<CAnimation> attackCursors;
+
 	/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
 	std::unique_ptr<Canvas> backgroundWithHexes;
 
@@ -66,8 +68,7 @@ class BattleFieldController : public CIntObject
 
 	/// Checks whether selected pixel is transparent, uses local coordinates of a hex
 	bool isPixelInHex(Point const & position);
-
-	BattleHex::EDir selectAttackDirection(BattleHex myNumber, const Point & point);
+	size_t selectBattleCursor(BattleHex myNumber);
 
 	void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
 	void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) override;
@@ -105,6 +106,7 @@ public:
 	/// returns true if stack should render its stack count image in default position - outside own hex
 	bool stackCountOutsideHex(const BattleHex & number) const;
 
-	void setBattleCursor(BattleHex myNumber);
+	BattleHex::EDir selectAttackDirection(BattleHex myNumber);
+
 	BattleHex fromWhichHexAttack(BattleHex myNumber);
 };

+ 4 - 3
client/gui/CursorHandler.h

@@ -127,9 +127,6 @@ class CursorHandler final
 
 	void changeGraphic(Cursor::Type type, size_t index);
 
-	Point getPivotOffsetDefault(size_t index);
-	Point getPivotOffsetMap(size_t index);
-	Point getPivotOffsetCombat(size_t index);
 	Point getPivotOffsetSpellcast();
 	Point getPivotOffset();
 
@@ -168,6 +165,10 @@ public:
 		return static_cast<Index>(frame);
 	}
 
+	Point getPivotOffsetDefault(size_t index);
+	Point getPivotOffsetMap(size_t index);
+	Point getPivotOffsetCombat(size_t index);
+
 	void render();
 
 	void hide();

+ 6 - 2
client/gui/EventDispatcher.cpp

@@ -221,7 +221,9 @@ void EventDispatcher::dispatchTextEditing(const std::string & text)
 
 void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPosition)
 {
-	for(auto it : panningInterested)
+	auto copied = panningInterested;
+
+	for(auto it : copied)
 	{
 		if (it->receiveEvent(initialPosition, AEventsReceiver::GESTURE_PANNING))
 		{
@@ -233,7 +235,9 @@ void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPositio
 
 void EventDispatcher::dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition)
 {
-	for(auto it : panningInterested)
+	auto copied = panningInterested;
+
+	for(auto it : copied)
 	{
 		if (it->isPanning())
 		{