mirror of
https://github.com/vcmi/vcmi.git
synced 2025-03-19 21:10:12 +02:00
Show cursor (including attack direction) when swiping in battle
This commit is contained in:
parent
db1045aecd
commit
ec55ec76b6
@ -160,7 +160,7 @@ void BattleActionsController::enterCreatureCastingMode()
|
|||||||
if (!isActiveStackSpellcaster())
|
if (!isActiveStackSpellcaster())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
for (auto const & action : possibleActions)
|
for(const auto & action : possibleActions)
|
||||||
{
|
{
|
||||||
if (action.get() != PossiblePlayerBattleAction::NO_LOCATION)
|
if (action.get() != PossiblePlayerBattleAction::NO_LOCATION)
|
||||||
continue;
|
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
|
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.creatureSpellsToCast.push_back(spell->id);
|
||||||
|
|
||||||
data.tacticsMode = owner.tacticsMode;
|
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
|
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())
|
switch(item.get())
|
||||||
{
|
{
|
||||||
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
|
case PossiblePlayerBattleAction::AIMED_SPELL_CREATURE:
|
||||||
case PossiblePlayerBattleAction::ANY_LOCATION:
|
case PossiblePlayerBattleAction::ANY_LOCATION:
|
||||||
case PossiblePlayerBattleAction::NO_LOCATION:
|
case PossiblePlayerBattleAction::NO_LOCATION:
|
||||||
case PossiblePlayerBattleAction::FREE_LOCATION:
|
case PossiblePlayerBattleAction::FREE_LOCATION:
|
||||||
case PossiblePlayerBattleAction::OBSTACLE:
|
case PossiblePlayerBattleAction::OBSTACLE:
|
||||||
if(!stack->hasBonusOfType(BonusType::NO_SPELLCAST_BY_DEFAULT) && context == MouseHoveredHexContext::OCCUPIED_HEX)
|
if(!stack->hasBonusOfType(BonusType::NO_SPELLCAST_BY_DEFAULT) && context == MouseHoveredHexContext::OCCUPIED_HEX)
|
||||||
return 1;
|
return 1;
|
||||||
else
|
else
|
||||||
return 100;//bottom priority
|
return 100; //bottom priority
|
||||||
break;
|
break;
|
||||||
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
|
case PossiblePlayerBattleAction::RANDOM_GENIE_SPELL:
|
||||||
return 2; break;
|
return 2;
|
||||||
case PossiblePlayerBattleAction::SHOOT:
|
break;
|
||||||
return 4; break;
|
case PossiblePlayerBattleAction::SHOOT:
|
||||||
case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
|
return 4;
|
||||||
return 5; break;
|
break;
|
||||||
case PossiblePlayerBattleAction::ATTACK:
|
case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
|
||||||
return 6; break;
|
return 5;
|
||||||
case PossiblePlayerBattleAction::WALK_AND_ATTACK:
|
break;
|
||||||
return 7; break;
|
case PossiblePlayerBattleAction::ATTACK:
|
||||||
case PossiblePlayerBattleAction::MOVE_STACK:
|
return 6;
|
||||||
return 8; break;
|
break;
|
||||||
case PossiblePlayerBattleAction::CATAPULT:
|
case PossiblePlayerBattleAction::WALK_AND_ATTACK:
|
||||||
return 9; break;
|
return 7;
|
||||||
case PossiblePlayerBattleAction::HEAL:
|
break;
|
||||||
return 10; break;
|
case PossiblePlayerBattleAction::MOVE_STACK:
|
||||||
case PossiblePlayerBattleAction::CREATURE_INFO:
|
return 8;
|
||||||
return 11; break;
|
break;
|
||||||
case PossiblePlayerBattleAction::HERO_INFO:
|
case PossiblePlayerBattleAction::CATAPULT:
|
||||||
return 12; break;
|
return 9;
|
||||||
case PossiblePlayerBattleAction::TELEPORT:
|
break;
|
||||||
return 13; break;
|
case PossiblePlayerBattleAction::HEAL:
|
||||||
default:
|
return 10;
|
||||||
assert(0);
|
break;
|
||||||
return 200; 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);
|
return assignPriority(lhs) < assignPriority(rhs);
|
||||||
};
|
};
|
||||||
@ -358,8 +371,26 @@ void BattleActionsController::actionSetCursor(PossiblePlayerBattleAction action,
|
|||||||
case PossiblePlayerBattleAction::ATTACK:
|
case PossiblePlayerBattleAction::ATTACK:
|
||||||
case PossiblePlayerBattleAction::WALK_AND_ATTACK:
|
case PossiblePlayerBattleAction::WALK_AND_ATTACK:
|
||||||
case PossiblePlayerBattleAction::ATTACK_AND_RETURN:
|
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;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
case PossiblePlayerBattleAction::SHOOT:
|
case PossiblePlayerBattleAction::SHOOT:
|
||||||
if (owner.curInt->cb->battleHasShootingPenalty(owner.stacksController->getActiveStack(), targetHex))
|
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));
|
TConstBonusListPtr bl = casterStack->getBonuses(Selector::type()(BonusType::SPELLCASTER));
|
||||||
|
|
||||||
for (auto const & bonus : *bl)
|
for(const auto & bonus : *bl)
|
||||||
{
|
{
|
||||||
if (bonus->additionalInfo[0] <= 0)
|
if (bonus->additionalInfo[0] <= 0)
|
||||||
creatureSpells.push_back(SpellID(bonus->subtype).toSpell());
|
creatureSpells.push_back(SpellID(bonus->subtype).toSpell());
|
||||||
|
@ -22,6 +22,7 @@
|
|||||||
|
|
||||||
#include "../CGameInfo.h"
|
#include "../CGameInfo.h"
|
||||||
#include "../CPlayerInterface.h"
|
#include "../CPlayerInterface.h"
|
||||||
|
#include "../render/CAnimation.h"
|
||||||
#include "../render/Canvas.h"
|
#include "../render/Canvas.h"
|
||||||
#include "../render/IImage.h"
|
#include "../render/IImage.h"
|
||||||
#include "../renderSDL/SDL_Extensions.h"
|
#include "../renderSDL/SDL_Extensions.h"
|
||||||
@ -46,6 +47,9 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
|
|||||||
cellUnitMovementHighlight = IImage::createFromFile("UnitMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
cellUnitMovementHighlight = IImage::createFromFile("UnitMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||||
cellUnitMaxMovementHighlight = IImage::createFromFile("UnitMaxMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
cellUnitMaxMovementHighlight = IImage::createFromFile("UnitMaxMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||||
|
|
||||||
|
attackCursors = std::make_shared<CAnimation>("CRCOMBAT");
|
||||||
|
attackCursors->preload();
|
||||||
|
|
||||||
if(!owner.siegeController)
|
if(!owner.siegeController)
|
||||||
{
|
{
|
||||||
auto bfieldType = owner.curInt->cb->battleGetBattlefieldType();
|
auto bfieldType = owner.curInt->cb->battleGetBattlefieldType();
|
||||||
@ -435,27 +439,7 @@ BattleHex BattleFieldController::getHexAtPosition(Point hoverPos)
|
|||||||
return BattleHex::INVALID;
|
return BattleHex::INVALID;
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleFieldController::setBattleCursor(BattleHex myNumber)
|
BattleHex::EDir BattleFieldController::selectAttackDirection(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)
|
|
||||||
{
|
{
|
||||||
const bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
|
const bool doubleWide = owner.stacksController->getActiveStack()->doubleWide();
|
||||||
auto neighbours = myNumber.allNeighbouringTiles();
|
auto neighbours = myNumber.allNeighbouringTiles();
|
||||||
@ -518,7 +502,7 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber,
|
|||||||
|
|
||||||
for (size_t i = 0; i < 8; ++i)
|
for (size_t i = 0; i < 8; ++i)
|
||||||
if (attackAvailability[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;
|
size_t nearest = -1;
|
||||||
for (size_t i = 0; i < 8; ++i)
|
for (size_t i = 0; i < 8; ++i)
|
||||||
@ -531,7 +515,7 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber,
|
|||||||
|
|
||||||
BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget)
|
BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget)
|
||||||
{
|
{
|
||||||
BattleHex::EDir direction = selectAttackDirection(getHoveredHex(), currentAttackOriginPoint);
|
BattleHex::EDir direction = selectAttackDirection(getHoveredHex());
|
||||||
|
|
||||||
const CStack * attacker = owner.stacksController->getActiveStack();
|
const CStack * attacker = owner.stacksController->getActiveStack();
|
||||||
|
|
||||||
@ -637,6 +621,14 @@ void BattleFieldController::show(Canvas & to)
|
|||||||
CSDL_Ext::CClipRectGuard guard(to.getInternalSurface(), pos);
|
CSDL_Ext::CClipRectGuard guard(to.getInternalSurface(), pos);
|
||||||
|
|
||||||
renderBattlefield(to);
|
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
|
bool BattleFieldController::receiveEvent(const Point & position, int eventType) const
|
||||||
|
@ -34,6 +34,8 @@ class BattleFieldController : public CIntObject
|
|||||||
std::shared_ptr<IImage> cellUnitMaxMovementHighlight;
|
std::shared_ptr<IImage> cellUnitMaxMovementHighlight;
|
||||||
std::shared_ptr<IImage> cellShade;
|
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
|
/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
|
||||||
std::unique_ptr<Canvas> backgroundWithHexes;
|
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
|
/// Checks whether selected pixel is transparent, uses local coordinates of a hex
|
||||||
bool isPixelInHex(Point const & position);
|
bool isPixelInHex(Point const & position);
|
||||||
|
size_t selectBattleCursor(BattleHex myNumber);
|
||||||
BattleHex::EDir selectAttackDirection(BattleHex myNumber, const Point & point);
|
|
||||||
|
|
||||||
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
void panning(bool on, const Point & initialPosition, const Point & finalPosition) override;
|
||||||
void gesturePanning(const Point & initialPosition, const Point & currentPosition, const Point & lastUpdateDistance) 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
|
/// returns true if stack should render its stack count image in default position - outside own hex
|
||||||
bool stackCountOutsideHex(const BattleHex & number) const;
|
bool stackCountOutsideHex(const BattleHex & number) const;
|
||||||
|
|
||||||
void setBattleCursor(BattleHex myNumber);
|
BattleHex::EDir selectAttackDirection(BattleHex myNumber);
|
||||||
|
|
||||||
BattleHex fromWhichHexAttack(BattleHex myNumber);
|
BattleHex fromWhichHexAttack(BattleHex myNumber);
|
||||||
};
|
};
|
||||||
|
@ -127,9 +127,6 @@ class CursorHandler final
|
|||||||
|
|
||||||
void changeGraphic(Cursor::Type type, size_t index);
|
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 getPivotOffsetSpellcast();
|
||||||
Point getPivotOffset();
|
Point getPivotOffset();
|
||||||
|
|
||||||
@ -168,6 +165,10 @@ public:
|
|||||||
return static_cast<Index>(frame);
|
return static_cast<Index>(frame);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Point getPivotOffsetDefault(size_t index);
|
||||||
|
Point getPivotOffsetMap(size_t index);
|
||||||
|
Point getPivotOffsetCombat(size_t index);
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
void hide();
|
void hide();
|
||||||
|
@ -221,7 +221,9 @@ void EventDispatcher::dispatchTextEditing(const std::string & text)
|
|||||||
|
|
||||||
void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPosition)
|
void EventDispatcher::dispatchGesturePanningStarted(const Point & initialPosition)
|
||||||
{
|
{
|
||||||
for(auto it : panningInterested)
|
auto copied = panningInterested;
|
||||||
|
|
||||||
|
for(auto it : copied)
|
||||||
{
|
{
|
||||||
if (it->receiveEvent(initialPosition, AEventsReceiver::GESTURE_PANNING))
|
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)
|
void EventDispatcher::dispatchGesturePanningEnded(const Point & initialPosition, const Point & finalPosition)
|
||||||
{
|
{
|
||||||
for(auto it : panningInterested)
|
auto copied = panningInterested;
|
||||||
|
|
||||||
|
for(auto it : copied)
|
||||||
{
|
{
|
||||||
if (it->isPanning())
|
if (it->isPanning())
|
||||||
{
|
{
|
||||||
|
Loading…
x
Reference in New Issue
Block a user