mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
Merge pull request #1874 from krs0/feature/separate_movement_highlight_for_hoverd_units_in_battle
Separate movement highlight for hovered units in battle
This commit is contained in:
commit
a97ebc2bf1
@ -271,7 +271,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack )
|
||||
BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector<BattleHex> hexes) const
|
||||
{
|
||||
auto reachability = cb->getReachability(stack);
|
||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack);
|
||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, true);
|
||||
|
||||
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
||||
{
|
||||
|
@ -15,7 +15,7 @@ PotentialTargets::PotentialTargets(const battle::Unit * attacker, const Hypothet
|
||||
{
|
||||
auto attackerInfo = state.battleGetUnitByID(attacker->unitId());
|
||||
auto reachability = state.getReachability(attackerInfo);
|
||||
auto avHexes = state.battleGetAvailableHexes(reachability, attackerInfo);
|
||||
auto avHexes = state.battleGetAvailableHexes(reachability, attackerInfo, true);
|
||||
|
||||
//FIXME: this should part of battleGetAvailableHexes
|
||||
bool forceTarget = false;
|
||||
|
@ -120,7 +120,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack )
|
||||
}
|
||||
else
|
||||
{
|
||||
std::vector<BattleHex> avHexes = cb->battleGetAvailableHexes(stack);
|
||||
std::vector<BattleHex> avHexes = cb->battleGetAvailableHexes(stack, true);
|
||||
|
||||
for (BattleHex hex : avHexes)
|
||||
{
|
||||
@ -238,7 +238,7 @@ void CStupidAI::print(const std::string &text) const
|
||||
BattleAction CStupidAI::goTowards(const CStack * stack, std::vector<BattleHex> hexes) const
|
||||
{
|
||||
auto reachability = cb->getReachability(stack);
|
||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack);
|
||||
auto avHexes = cb->battleGetAvailableHexes(reachability, stack, false);
|
||||
|
||||
if(!avHexes.size() || !hexes.size()) //we are blocked or dest is blocked
|
||||
{
|
||||
|
BIN
Mods/vcmi/Data/UnitMaxMovementHighlight.png
Normal file
BIN
Mods/vcmi/Data/UnitMaxMovementHighlight.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 422 B |
BIN
Mods/vcmi/Data/UnitMovementHighlight.png
Normal file
BIN
Mods/vcmi/Data/UnitMovementHighlight.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 272 B |
@ -81,6 +81,8 @@
|
||||
"vcmi.battleOptions.animationsSpeed6.help": "Set animation speed to instantaneous",
|
||||
"vcmi.battleOptions.touchscreenMode.hover": "Touchscreen mode",
|
||||
"vcmi.battleOptions.touchscreenMode.help": "{Touchscreen mode}\n\nIf enabled, second click is required to confirm and execute action. This is more suitable for touchscreen devices.",
|
||||
"vcmi.battleOptions.movementHighlightOnHover.hover": "Movement Highlight on Hover",
|
||||
"vcmi.battleOptions.movementHighlightOnHover.help": "{Movement Highlight on Hover}\n\nHighlight unit's movement range when you hover over it.",
|
||||
"vcmi.battleOptions.skipBattleIntroMusic.hover": "Skip Intro Music",
|
||||
"vcmi.battleOptions.skipBattleIntroMusic.help": "{Skip Intro Music}\n\nAllow actions during the intro music that plays at the beginning of each battle",
|
||||
"vcmi.battleWindow.pressKeyToSkipIntro" : "Press any key to start battle immediately",
|
||||
|
@ -50,6 +50,7 @@
|
||||
"description" : "Ключові файли необхідні для повноцінної роботи VCMI",
|
||||
"author" : "Команда VCMI",
|
||||
|
||||
"skipValidation" : true,
|
||||
"translations" : [
|
||||
"config/vcmi/ukrainian.json"
|
||||
]
|
||||
|
@ -623,7 +623,7 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B
|
||||
{
|
||||
if(owner.stacksController->getActiveStack()->doubleWide())
|
||||
{
|
||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack());
|
||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack(), true);
|
||||
BattleHex shiftedDest = targetHex.cloneInDirection(owner.stacksController->getActiveStack()->destShiftDir(), false);
|
||||
if(vstd::contains(acc, targetHex))
|
||||
owner.giveCommand(EActionType::WALK, targetHex);
|
||||
@ -926,7 +926,7 @@ bool BattleActionsController::isCastingPossibleHere(const CSpell * currentSpell,
|
||||
|
||||
bool BattleActionsController::canStackMoveHere(const CStack * stackToMove, BattleHex myNumber) const
|
||||
{
|
||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove);
|
||||
std::vector<BattleHex> acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove, false);
|
||||
BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false);
|
||||
|
||||
if (vstd::contains(acc, myNumber))
|
||||
|
@ -44,6 +44,8 @@ BattleFieldController::BattleFieldController(BattleInterface & owner):
|
||||
//preparing cells and hexes
|
||||
cellBorder = IImage::createFromFile("CCELLGRD.BMP", EImageBlitMode::COLORKEY);
|
||||
cellShade = IImage::createFromFile("CCELLSHD.BMP");
|
||||
cellUnitMovementHighlight = IImage::createFromFile("UnitMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||
cellUnitMaxMovementHighlight = IImage::createFromFile("UnitMaxMovementHighlight.PNG", EImageBlitMode::COLORKEY);
|
||||
|
||||
if(!owner.siegeController)
|
||||
{
|
||||
@ -138,7 +140,6 @@ void BattleFieldController::showBackground(Canvas & canvas)
|
||||
showBackgroundImage(canvas);
|
||||
|
||||
showHighlightedHexes(canvas);
|
||||
|
||||
}
|
||||
|
||||
void BattleFieldController::showBackgroundImage(Canvas & canvas)
|
||||
@ -172,32 +173,34 @@ void BattleFieldController::redrawBackgroundWithHexes()
|
||||
{
|
||||
const CStack *activeStack = owner.stacksController->getActiveStack();
|
||||
std::vector<BattleHex> attackableHexes;
|
||||
if (activeStack)
|
||||
occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes);
|
||||
if(activeStack)
|
||||
occupiableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, true, &attackableHexes);
|
||||
|
||||
//prepare background graphic with hexes and shaded hexes
|
||||
// prepare background graphic with hexes and shaded hexes
|
||||
backgroundWithHexes->draw(background, Point(0,0));
|
||||
owner.obstacleController->showAbsoluteObstacles(*backgroundWithHexes);
|
||||
if ( owner.siegeController )
|
||||
if(owner.siegeController)
|
||||
owner.siegeController->showAbsoluteObstacles(*backgroundWithHexes);
|
||||
|
||||
if (settings["battle"]["stackRange"].Bool())
|
||||
// show shaded hexes for active's stack valid movement and the hexes that it can attack
|
||||
if(settings["battle"]["stackRange"].Bool())
|
||||
{
|
||||
std::vector<BattleHex> hexesToShade = occupyableHexes;
|
||||
std::vector<BattleHex> hexesToShade = occupiableHexes;
|
||||
hexesToShade.insert(hexesToShade.end(), attackableHexes.begin(), attackableHexes.end());
|
||||
for (BattleHex hex : hexesToShade)
|
||||
for(BattleHex hex : hexesToShade)
|
||||
{
|
||||
backgroundWithHexes->draw(cellShade, hexPositionLocal(hex).topLeft());
|
||||
showHighlightedHex(*backgroundWithHexes, cellShade, hex, false);
|
||||
}
|
||||
}
|
||||
|
||||
// draw cell borders
|
||||
if(settings["battle"]["cellBorders"].Bool())
|
||||
{
|
||||
for (int i=0; i<GameConstants::BFIELD_SIZE; ++i)
|
||||
for(int i=0; i<GameConstants::BFIELD_SIZE; ++i)
|
||||
{
|
||||
if ( i % GameConstants::BFIELD_WIDTH == 0)
|
||||
if(i % GameConstants::BFIELD_WIDTH == 0)
|
||||
continue;
|
||||
if ( i % GameConstants::BFIELD_WIDTH == GameConstants::BFIELD_WIDTH - 1)
|
||||
if(i % GameConstants::BFIELD_WIDTH == GameConstants::BFIELD_WIDTH - 1)
|
||||
continue;
|
||||
|
||||
backgroundWithHexes->draw(cellBorder, hexPositionLocal(i).topLeft());
|
||||
@ -205,23 +208,23 @@ void BattleFieldController::redrawBackgroundWithHexes()
|
||||
}
|
||||
}
|
||||
|
||||
void BattleFieldController::showHighlightedHex(Canvas & canvas, BattleHex hex, bool darkBorder)
|
||||
void BattleFieldController::showHighlightedHex(Canvas & canvas, std::shared_ptr<IImage> highlight, BattleHex hex, bool darkBorder)
|
||||
{
|
||||
Point hexPos = hexPositionLocal(hex).topLeft();
|
||||
|
||||
canvas.draw(cellShade, hexPos);
|
||||
canvas.draw(highlight, hexPos);
|
||||
if(!darkBorder && settings["battle"]["cellBorders"].Bool())
|
||||
canvas.draw(cellBorder, hexPos);
|
||||
}
|
||||
|
||||
std::set<BattleHex> BattleFieldController::getHighlightedHexesStackRange()
|
||||
std::set<BattleHex> BattleFieldController::getHighlightedHexesForActiveStack()
|
||||
{
|
||||
std::set<BattleHex> result;
|
||||
|
||||
if ( !owner.stacksController->getActiveStack())
|
||||
if(!owner.stacksController->getActiveStack())
|
||||
return result;
|
||||
|
||||
if ( !settings["battle"]["stackRange"].Bool())
|
||||
if(!settings["battle"]["stackRange"].Bool())
|
||||
return result;
|
||||
|
||||
auto hoveredHex = getHoveredHex();
|
||||
@ -230,18 +233,33 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesStackRange()
|
||||
for(BattleHex hex : set)
|
||||
result.insert(hex);
|
||||
|
||||
// display the movement shadow of stack under mouse
|
||||
return result;
|
||||
}
|
||||
|
||||
std::set<BattleHex> BattleFieldController::getMovementRangeForHoveredStack()
|
||||
{
|
||||
std::set<BattleHex> result;
|
||||
|
||||
if (!owner.stacksController->getActiveStack())
|
||||
return result;
|
||||
|
||||
if (!settings["battle"]["movementHighlightOnHover"].Bool())
|
||||
return result;
|
||||
|
||||
auto hoveredHex = getHoveredHex();
|
||||
|
||||
// add possible movement hexes for stack under mouse
|
||||
const CStack * const hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
if(hoveredStack && hoveredStack != owner.stacksController->getActiveStack())
|
||||
if(hoveredStack)
|
||||
{
|
||||
std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(hoveredStack, true, nullptr);
|
||||
std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(hoveredStack, false, true, nullptr);
|
||||
for(BattleHex hex : v)
|
||||
result.insert(hex);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
|
||||
std::set<BattleHex> BattleFieldController::getHighlightedHexesForSpellRange()
|
||||
{
|
||||
std::set<BattleHex> result;
|
||||
auto hoveredHex = getHoveredHex();
|
||||
@ -260,9 +278,9 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesSpellRange()
|
||||
{
|
||||
// printing shaded hex(es)
|
||||
spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
|
||||
auto shaded = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
|
||||
auto shadedHexes = spell->battleMechanics(&event)->rangeInHexes(hoveredHex);
|
||||
|
||||
for(BattleHex shadedHex : shaded)
|
||||
for(BattleHex shadedHex : shadedHexes)
|
||||
{
|
||||
if((shadedHex.getX() != 0) && (shadedHex.getX() != GameConstants::BFIELD_WIDTH - 1))
|
||||
result.insert(shadedHex);
|
||||
@ -276,72 +294,73 @@ std::set<BattleHex> BattleFieldController::getHighlightedHexesMovementTarget()
|
||||
const CStack * stack = owner.stacksController->getActiveStack();
|
||||
auto hoveredHex = getHoveredHex();
|
||||
|
||||
if (stack)
|
||||
if(!stack)
|
||||
return {};
|
||||
|
||||
std::vector<BattleHex> availableHexes = owner.curInt->cb->battleGetAvailableHexes(stack, true, false, nullptr);
|
||||
|
||||
auto hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
if(owner.curInt->cb->battleCanAttack(stack, hoveredStack, hoveredHex))
|
||||
{
|
||||
std::vector<BattleHex> v = owner.curInt->cb->battleGetAvailableHexes(stack, false, nullptr);
|
||||
|
||||
auto hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
|
||||
if(owner.curInt->cb->battleCanAttack(stack, hoveredStack, hoveredHex))
|
||||
if(isTileAttackable(hoveredHex))
|
||||
{
|
||||
if (isTileAttackable(hoveredHex))
|
||||
{
|
||||
BattleHex attackFromHex = fromWhichHexAttack(hoveredHex);
|
||||
BattleHex attackFromHex = fromWhichHexAttack(hoveredHex);
|
||||
|
||||
if (stack->doubleWide())
|
||||
return {attackFromHex, stack->occupiedHex(attackFromHex)};
|
||||
else
|
||||
return {attackFromHex};
|
||||
}
|
||||
}
|
||||
|
||||
if (vstd::contains(v,hoveredHex))
|
||||
{
|
||||
if (stack->doubleWide())
|
||||
return {hoveredHex, stack->occupiedHex(hoveredHex)};
|
||||
if(stack->doubleWide())
|
||||
return {attackFromHex, stack->occupiedHex(attackFromHex)};
|
||||
else
|
||||
return {hoveredHex};
|
||||
}
|
||||
if (stack->doubleWide())
|
||||
{
|
||||
for (auto const & hex : v)
|
||||
{
|
||||
if (stack->occupiedHex(hex) == hoveredHex)
|
||||
return { hoveredHex, hex };
|
||||
}
|
||||
return {attackFromHex};
|
||||
}
|
||||
}
|
||||
|
||||
if(vstd::contains(availableHexes, hoveredHex))
|
||||
{
|
||||
if(stack->doubleWide())
|
||||
return {hoveredHex, stack->occupiedHex(hoveredHex)};
|
||||
else
|
||||
return {hoveredHex};
|
||||
}
|
||||
|
||||
if(stack->doubleWide())
|
||||
{
|
||||
for(auto const & hex : availableHexes)
|
||||
{
|
||||
if(stack->occupiedHex(hex) == hoveredHex)
|
||||
return {hoveredHex, hex};
|
||||
}
|
||||
}
|
||||
|
||||
return {};
|
||||
}
|
||||
|
||||
void BattleFieldController::showHighlightedHexes(Canvas & canvas)
|
||||
{
|
||||
std::set<BattleHex> hoveredStack = getHighlightedHexesStackRange();
|
||||
std::set<BattleHex> hoveredSpell = getHighlightedHexesSpellRange();
|
||||
std::set<BattleHex> hoveredMove = getHighlightedHexesMovementTarget();
|
||||
std::set<BattleHex> hoveredStackMovementRangeHexes = getMovementRangeForHoveredStack();
|
||||
std::set<BattleHex> hoveredSpellHexes = getHighlightedHexesForSpellRange();
|
||||
std::set<BattleHex> hoveredMoveHexes = getHighlightedHexesMovementTarget();
|
||||
|
||||
if (getHoveredHex() == BattleHex::INVALID)
|
||||
if(getHoveredHex() == BattleHex::INVALID)
|
||||
return;
|
||||
|
||||
auto const & hoveredMouse = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpell : hoveredMove;
|
||||
auto const & hoveredMouseHexes = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpellHexes : hoveredMoveHexes;
|
||||
|
||||
for(int b=0; b<GameConstants::BFIELD_SIZE; ++b)
|
||||
for(int hex = 0; hex < GameConstants::BFIELD_SIZE; ++hex)
|
||||
{
|
||||
bool stack = hoveredStack.count(b);
|
||||
bool mouse = hoveredMouse.count(b);
|
||||
bool stackMovement = hoveredStackMovementRangeHexes.count(hex);
|
||||
bool mouse = hoveredMouseHexes.count(hex);
|
||||
|
||||
if ( stack && mouse )
|
||||
if(stackMovement && mouse) // area where hovered stackMovement can move shown with highlight. Because also affected by mouse cursor, shade as well
|
||||
{
|
||||
// area where enemy stack can move AND affected by mouse cursor - create darker highlight by blitting twice
|
||||
showHighlightedHex(canvas, b, true);
|
||||
showHighlightedHex(canvas, b, true);
|
||||
showHighlightedHex(canvas, cellUnitMovementHighlight, hex, false);
|
||||
showHighlightedHex(canvas, cellShade, hex, true);
|
||||
}
|
||||
if ( !stack && mouse )
|
||||
if(!stackMovement && mouse) // hexes affected only at mouse cursor shown as shaded
|
||||
{
|
||||
showHighlightedHex(canvas, b, true);
|
||||
showHighlightedHex(canvas, cellShade, hex, true);
|
||||
}
|
||||
if ( stack && !mouse )
|
||||
if(stackMovement && !mouse) // hexes where hovered stackMovement can move shown with highlight
|
||||
{
|
||||
showHighlightedHex(canvas, b, false);
|
||||
showHighlightedHex(canvas, cellUnitMovementHighlight, hex, false);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -438,18 +457,18 @@ BattleHex::EDir BattleFieldController::selectAttackDirection(BattleHex myNumber,
|
||||
// | - - | - - | - - | - o o | o o - | - - | - - | o o
|
||||
|
||||
for (size_t i : { 1, 2, 3})
|
||||
attackAvailability[i] = vstd::contains(occupyableHexes, neighbours[i]) && vstd::contains(occupyableHexes, neighbours[i].cloneInDirection(BattleHex::RIGHT, false));
|
||||
attackAvailability[i] = vstd::contains(occupiableHexes, neighbours[i]) && vstd::contains(occupiableHexes, neighbours[i].cloneInDirection(BattleHex::RIGHT, false));
|
||||
|
||||
for (size_t i : { 4, 5, 0})
|
||||
attackAvailability[i] = vstd::contains(occupyableHexes, neighbours[i]) && vstd::contains(occupyableHexes, neighbours[i].cloneInDirection(BattleHex::LEFT, false));
|
||||
attackAvailability[i] = vstd::contains(occupiableHexes, neighbours[i]) && vstd::contains(occupiableHexes, neighbours[i].cloneInDirection(BattleHex::LEFT, false));
|
||||
|
||||
attackAvailability[6] = vstd::contains(occupyableHexes, neighbours[0]) && vstd::contains(occupyableHexes, neighbours[1]);
|
||||
attackAvailability[7] = vstd::contains(occupyableHexes, neighbours[3]) && vstd::contains(occupyableHexes, neighbours[4]);
|
||||
attackAvailability[6] = vstd::contains(occupiableHexes, neighbours[0]) && vstd::contains(occupiableHexes, neighbours[1]);
|
||||
attackAvailability[7] = vstd::contains(occupiableHexes, neighbours[3]) && vstd::contains(occupiableHexes, neighbours[4]);
|
||||
}
|
||||
else
|
||||
{
|
||||
for (size_t i = 0; i < 6; ++i)
|
||||
attackAvailability[i] = vstd::contains(occupyableHexes, neighbours[i]);
|
||||
attackAvailability[i] = vstd::contains(occupiableHexes, neighbours[i]);
|
||||
|
||||
attackAvailability[6] = false;
|
||||
attackAvailability[7] = false;
|
||||
@ -561,7 +580,7 @@ BattleHex BattleFieldController::fromWhichHexAttack(BattleHex attackTarget)
|
||||
|
||||
bool BattleFieldController::isTileAttackable(const BattleHex & number) const
|
||||
{
|
||||
for (auto & elem : occupyableHexes)
|
||||
for (auto & elem : occupiableHexes)
|
||||
{
|
||||
if (BattleHex::mutualPosition(elem, number) != -1 || elem == number)
|
||||
return true;
|
||||
|
@ -32,6 +32,8 @@ class BattleFieldController : public CIntObject
|
||||
|
||||
std::shared_ptr<IImage> background;
|
||||
std::shared_ptr<IImage> cellBorder;
|
||||
std::shared_ptr<IImage> cellUnitMovementHighlight;
|
||||
std::shared_ptr<IImage> cellUnitMaxMovementHighlight;
|
||||
std::shared_ptr<IImage> cellShade;
|
||||
|
||||
/// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack
|
||||
@ -41,15 +43,16 @@ class BattleFieldController : public CIntObject
|
||||
BattleHex attackingHex;
|
||||
|
||||
/// hexes to which currently active stack can move
|
||||
std::vector<BattleHex> occupyableHexes;
|
||||
std::vector<BattleHex> occupiableHexes;
|
||||
|
||||
/// hexes that when in front of a unit cause it's amount box to move back
|
||||
std::array<bool, GameConstants::BFIELD_SIZE> stackCountOutsideHexes;
|
||||
|
||||
void showHighlightedHex(Canvas & to, BattleHex hex, bool darkBorder);
|
||||
void showHighlightedHex(Canvas & to, std::shared_ptr<IImage> highlight, BattleHex hex, bool darkBorder);
|
||||
|
||||
std::set<BattleHex> getHighlightedHexesStackRange();
|
||||
std::set<BattleHex> getHighlightedHexesSpellRange();
|
||||
std::set<BattleHex> getHighlightedHexesForActiveStack();
|
||||
std::set<BattleHex> getMovementRangeForHoveredStack();
|
||||
std::set<BattleHex> getHighlightedHexesForSpellRange();
|
||||
std::set<BattleHex> getHighlightedHexesMovementTarget();
|
||||
|
||||
void showBackground(Canvas & canvas);
|
||||
|
@ -198,6 +198,23 @@ void BattleWindow::keyPressed(const SDL_Keycode & key)
|
||||
{
|
||||
owner.actionsController->endCastingSpell();
|
||||
}
|
||||
else if(GH.isKeyboardShiftDown())
|
||||
{
|
||||
// save and activate setting
|
||||
Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"];
|
||||
movementHighlightOnHoverCache = movementHighlightOnHover->Bool();
|
||||
movementHighlightOnHover->Bool() = true;
|
||||
}
|
||||
}
|
||||
|
||||
void BattleWindow::keyReleased(const SDL_Keycode & key)
|
||||
{
|
||||
if(!GH.isKeyboardShiftDown())
|
||||
{
|
||||
// set back to initial state
|
||||
Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"];
|
||||
movementHighlightOnHover->Bool() = movementHighlightOnHoverCache;
|
||||
}
|
||||
}
|
||||
|
||||
void BattleWindow::clickRight(tribool down, bool previousState)
|
||||
|
@ -85,6 +85,7 @@ public:
|
||||
void activate() override;
|
||||
void deactivate() override;
|
||||
void keyPressed(const SDL_Keycode & key) override;
|
||||
void keyReleased(const SDL_Keycode& key) override;
|
||||
void clickRight(tribool down, bool previousState) override;
|
||||
void show(SDL_Surface *to) override;
|
||||
void showAll(SDL_Surface *to) override;
|
||||
@ -98,5 +99,8 @@ public:
|
||||
/// Set possible alternative options. If more than 1 - the last will be considered as default option
|
||||
void setAlternativeActions(const std::list<PossiblePlayerBattleAction> &);
|
||||
|
||||
private:
|
||||
/// used to save the state of this setting on toggle.
|
||||
bool movementHighlightOnHoverCache;
|
||||
};
|
||||
|
||||
|
@ -418,7 +418,7 @@ void CGuiHandler::handleCurrentEvent( SDL_Event & current )
|
||||
for(auto i = miCopy.begin(); i != miCopy.end() && continueEventHandling; i++)
|
||||
if(vstd::contains(keyinterested,*i) && (!keysCaptured || (*i)->captureThisKey(key.keysym.sym)))
|
||||
{
|
||||
if (key.state == SDL_PRESSED)
|
||||
if (key.state == SDL_PRESSED && key.repeat == 0) // function like key_DOWN, and not like a periodic key_Pressed check
|
||||
(**i).keyPressed(key.keysym.sym);
|
||||
if (key.state == SDL_RELEASED)
|
||||
(**i).keyReleased(key.keysym.sym);
|
||||
|
@ -34,6 +34,10 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
|
||||
{
|
||||
movementShadowChangedCallback(value, owner);
|
||||
});
|
||||
addCallback("movementHighlightOnHoverChanged", [this, owner](bool value)
|
||||
{
|
||||
movementHighlightOnHoverChangedCallback(value, owner);
|
||||
});
|
||||
addCallback("mouseShadowChanged", [this](bool value)
|
||||
{
|
||||
mouseShadowChangedCallback(value);
|
||||
@ -72,6 +76,9 @@ BattleOptionsTab::BattleOptionsTab(BattleInterface * owner)
|
||||
std::shared_ptr<CToggleButton> movementShadowCheckbox = widget<CToggleButton>("movementShadowCheckbox");
|
||||
movementShadowCheckbox->setSelected(settings["battle"]["stackRange"].Bool());
|
||||
|
||||
std::shared_ptr<CToggleButton> movementHighlightOnHoverCheckbox = widget<CToggleButton>("movementHighlightOnHoverCheckbox");
|
||||
movementHighlightOnHoverCheckbox->setSelected(settings["battle"]["movementHighlightOnHover"].Bool());
|
||||
|
||||
std::shared_ptr<CToggleButton> mouseShadowCheckbox = widget<CToggleButton>("mouseShadowCheckbox");
|
||||
mouseShadowCheckbox->setSelected(settings["battle"]["mouseShadow"].Bool());
|
||||
|
||||
@ -138,6 +145,14 @@ void BattleOptionsTab::movementShadowChangedCallback(bool value, BattleInterface
|
||||
parentBattleInterface->redrawBattlefield();
|
||||
}
|
||||
|
||||
void BattleOptionsTab::movementHighlightOnHoverChangedCallback(bool value, BattleInterface * parentBattleInterface)
|
||||
{
|
||||
Settings stackRange = settings.write["battle"]["movementHighlightOnHover"];
|
||||
stackRange->Bool() = value;
|
||||
if(parentBattleInterface)
|
||||
parentBattleInterface->redrawBattlefield();
|
||||
}
|
||||
|
||||
void BattleOptionsTab::mouseShadowChangedCallback(bool value)
|
||||
{
|
||||
Settings shadow = settings.write["battle"]["mouseShadow"];
|
||||
|
@ -24,6 +24,7 @@ private:
|
||||
std::string getQueueSizeStringFromId(int value) const;
|
||||
void viewGridChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||
void movementShadowChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||
void movementHighlightOnHoverChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||
void mouseShadowChangedCallback(bool value);
|
||||
void animationSpeedChangedCallback(int value);
|
||||
void showQueueChangedCallback(bool value, BattleInterface * parentBattleInterface);
|
||||
|
@ -286,7 +286,7 @@
|
||||
"type" : "object",
|
||||
"additionalProperties" : false,
|
||||
"default": {},
|
||||
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "showQueue", "queueSize", "touchscreenMode" ],
|
||||
"required" : [ "speedFactor", "mouseShadow", "cellBorders", "stackRange", "movementHighlightOnHover", "showQueue", "queueSize", "touchscreenMode" ],
|
||||
"properties" : {
|
||||
"speedFactor" : {
|
||||
"type" : "number",
|
||||
@ -308,6 +308,10 @@
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"movementHighlightOnHover" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
},
|
||||
"showQueue" : {
|
||||
"type" : "boolean",
|
||||
"default" : true
|
||||
|
@ -142,13 +142,17 @@
|
||||
"position": {"x": 45, "y": 85}
|
||||
},
|
||||
{
|
||||
"text": "core.genrltxt.406",
|
||||
"text": "vcmi.battleOptions.movementHighlightOnHover.hover",
|
||||
"position": {"x": 45, "y": 115}
|
||||
},
|
||||
{
|
||||
"text": "core.genrltxt.407",
|
||||
"text": "core.genrltxt.406",
|
||||
"position": {"x": 45, "y": 145}
|
||||
},
|
||||
{
|
||||
"text": "core.genrltxt.407",
|
||||
"position": {"x": 45, "y": 175}
|
||||
},
|
||||
{
|
||||
"text": "vcmi.battleOptions.skipBattleIntroMusic.hover",
|
||||
"position": {"x": 45, "y": 175}
|
||||
@ -176,26 +180,34 @@
|
||||
"position": {"x": 10, "y": 83},
|
||||
"callback": "movementShadowChanged"
|
||||
},
|
||||
{
|
||||
"name": "movementHighlightOnHoverCheckbox",
|
||||
"type": "toggleButton",
|
||||
"image": "sysopchk.def",
|
||||
"help": "vcmi.battleOptions.movementHighlightOnHover",
|
||||
"position": {"x": 10, "y": 113},
|
||||
"callback": "movementHighlightOnHoverChanged"
|
||||
},
|
||||
{
|
||||
"name": "mouseShadowCheckbox",
|
||||
"type": "toggleButton",
|
||||
"image": "sysopchk.def",
|
||||
"help": "core.help.429",
|
||||
"position": {"x": 10, "y": 113},
|
||||
"position": {"x": 10, "y": 143},
|
||||
"callback": "mouseShadowChanged"
|
||||
},
|
||||
{
|
||||
"name": "battleFieldCasualtiesPlaceholder",
|
||||
"type": "picture",
|
||||
"image": "settingsWindow/checkBoxEmpty",
|
||||
"position": {"x": 10, "y": 143},
|
||||
"position": {"x": 10, "y": 173},
|
||||
},
|
||||
{
|
||||
"name": "skipBattleIntroMusicCheckbox",
|
||||
"type": "toggleButton",
|
||||
"image": "sysopchk.def",
|
||||
"help": "vcmi.battleOptions.skipBattleIntroMusic",
|
||||
"position": {"x": 10, "y": 173},
|
||||
"position": {"x": 10, "y": 203},
|
||||
"callback": "skipBattleIntroMusicChanged"
|
||||
},
|
||||
{
|
||||
|
@ -538,7 +538,7 @@ void CBattleInfoCallback::battleGetTurnOrder(std::vector<battle::Units> & turns,
|
||||
battleGetTurnOrder(turns, maxUnits, maxTurns, actualTurn + 1, sideThatLastMoved);
|
||||
}
|
||||
|
||||
std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit) const
|
||||
std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack) const
|
||||
{
|
||||
|
||||
RETURN_IF_NOT_BATTLE(std::vector<BattleHex>());
|
||||
@ -547,10 +547,10 @@ std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const battle
|
||||
|
||||
auto reachability = getReachability(unit);
|
||||
|
||||
return battleGetAvailableHexes(reachability, unit);
|
||||
return battleGetAvailableHexes(reachability, unit, isActiveStack);
|
||||
}
|
||||
|
||||
std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit) const
|
||||
std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit, bool isActiveStack) const
|
||||
{
|
||||
std::vector<BattleHex> ret;
|
||||
|
||||
@ -560,7 +560,7 @@ std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const Reacha
|
||||
|
||||
auto unitSpeed = unit->Speed(0, true);
|
||||
|
||||
const bool tacticPhase = battleTacticDist() && battleGetTacticsSide() == unit->unitSide();
|
||||
const bool showTacticsRange = battleTacticDist() && battleGetTacticsSide() == unit->unitSide() && isActiveStack;
|
||||
|
||||
for(int i = 0; i < GameConstants::BFIELD_SIZE; ++i)
|
||||
{
|
||||
@ -568,15 +568,15 @@ std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const Reacha
|
||||
if(!cache.isReachable(i))
|
||||
continue;
|
||||
|
||||
if(tacticPhase)
|
||||
if(showTacticsRange)
|
||||
{
|
||||
//Stack has to perform tactic-phase movement -> can enter any reachable tile within given range
|
||||
// Stack has to perform tactic-phase movement -> can enter any reachable tile within given range
|
||||
if(!isInTacticRange(i))
|
||||
continue;
|
||||
}
|
||||
else
|
||||
{
|
||||
//Not tactics phase -> destination must be reachable and within unit range.
|
||||
// Not tactics phase -> destination must be reachable and within unit range.
|
||||
if(cache.distances[i] > static_cast<int>(unitSpeed))
|
||||
continue;
|
||||
}
|
||||
@ -587,10 +587,9 @@ std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const Reacha
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit, bool addOccupiable, std::vector<BattleHex> * attackable) const
|
||||
std::vector<BattleHex> CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack, bool addOccupiable, std::vector<BattleHex> * attackable) const
|
||||
{
|
||||
std::vector<BattleHex> ret = battleGetAvailableHexes(unit);
|
||||
std::vector<BattleHex> ret = battleGetAvailableHexes(unit, isActiveStack);
|
||||
|
||||
if(ret.empty())
|
||||
return ret;
|
||||
@ -976,7 +975,6 @@ ReachabilityInfo CBattleInfoCallback::makeBFS(const AccessibilityInfo &accessibi
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
bool CBattleInfoCallback::isInObstacle(
|
||||
BattleHex hex,
|
||||
const std::set<BattleHex> & obstacles,
|
||||
@ -1030,7 +1028,7 @@ std::set<BattleHex> CBattleInfoCallback::getStoppers(BattlePerspective::BattlePe
|
||||
std::pair<const battle::Unit *, BattleHex> CBattleInfoCallback::getNearestStack(const battle::Unit * closest) const
|
||||
{
|
||||
auto reachability = getReachability(closest);
|
||||
auto avHexes = battleGetAvailableHexes(reachability, closest);
|
||||
auto avHexes = battleGetAvailableHexes(reachability, closest, false);
|
||||
|
||||
// I hate std::pairs with their undescriptive member names first / second
|
||||
struct DistStack
|
||||
@ -1097,7 +1095,6 @@ BattleHex CBattleInfoCallback::getAvaliableHex(const CreatureID & creID, ui8 sid
|
||||
return BattleHex::getClosestTile(side, pos, occupyable);
|
||||
}
|
||||
|
||||
|
||||
si8 CBattleInfoCallback::battleGetTacticDist() const
|
||||
{
|
||||
RETURN_IF_NOT_BATTLE(0);
|
||||
@ -1158,7 +1155,7 @@ ReachabilityInfo CBattleInfoCallback::getFlyingReachability(const ReachabilityIn
|
||||
return ret;
|
||||
}
|
||||
|
||||
AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const battle::Unit* attacker, BattleHex destinationTile, BattleHex attackerPos) const
|
||||
AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes(const battle::Unit* attacker, BattleHex destinationTile, BattleHex attackerPos) const
|
||||
{
|
||||
//does not return hex attacked directly
|
||||
AttackableTiles at;
|
||||
@ -1242,7 +1239,7 @@ AttackableTiles CBattleInfoCallback::getPotentiallyAttackableHexes (const battl
|
||||
return at;
|
||||
}
|
||||
|
||||
AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::Unit * attacker, BattleHex destinationTile, BattleHex attackerPos) const
|
||||
AttackableTiles CBattleInfoCallback::getPotentiallyShootableHexes(const battle::Unit * attacker, BattleHex destinationTile, BattleHex attackerPos) const
|
||||
{
|
||||
//does not return hex attacked directly
|
||||
AttackableTiles at;
|
||||
|
@ -74,12 +74,12 @@ public:
|
||||
void battleGetTurnOrder(std::vector<battle::Units> & out, const size_t maxUnits, const int maxTurns, const int turn = 0, int8_t lastMoved = -1) const;
|
||||
|
||||
///returns reachable hexes (valid movement destinations), DOES contain stack current position
|
||||
std::vector<BattleHex> battleGetAvailableHexes(const battle::Unit * unit, bool addOccupiable, std::vector<BattleHex> * attackable) const;
|
||||
std::vector<BattleHex> battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack, bool addOccupiable, std::vector<BattleHex> * attackable) const;
|
||||
|
||||
///returns reachable hexes (valid movement destinations), DOES contain stack current position (lite version)
|
||||
std::vector<BattleHex> battleGetAvailableHexes(const battle::Unit * unit) const;
|
||||
std::vector<BattleHex> battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack) const;
|
||||
|
||||
std::vector<BattleHex> battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit) const;
|
||||
std::vector<BattleHex> battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit, bool isActiveStack) const;
|
||||
|
||||
int battleGetSurrenderCost(const PlayerColor & Player) const; //returns cost of surrendering battle, -1 if surrendering is not possible
|
||||
ReachabilityInfo::TDistances battleGetDistances(const battle::Unit * unit, BattleHex assumedPosition) const;
|
||||
|
Loading…
x
Reference in New Issue
Block a user