From e1c388465a580ca8550bd2513373319614c98023 Mon Sep 17 00:00:00 2001 From: krs Date: Wed, 22 Mar 2023 22:51:00 +0200 Subject: [PATCH 1/9] HD mod highlighting of movement for hovered stack. Does not work as intended in tactics mode. --- Mods/vcmi/Data/CCNSSh2.png | Bin 0 -> 1370 bytes Mods/vcmi/Data/CCNSShd.png | Bin 0 -> 858 bytes client/battle/BattleFieldController.cpp | 153 ++++++++++++++---------- client/battle/BattleFieldController.h | 9 +- 4 files changed, 99 insertions(+), 63 deletions(-) create mode 100644 Mods/vcmi/Data/CCNSSh2.png create mode 100644 Mods/vcmi/Data/CCNSShd.png diff --git a/Mods/vcmi/Data/CCNSSh2.png b/Mods/vcmi/Data/CCNSSh2.png new file mode 100644 index 0000000000000000000000000000000000000000..2685b035135a0a20325776698e248c234abbe78e GIT binary patch literal 1370 zcmV-g1*Q6lP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!2kdb!2!6DYwZ941n)^iK~!i%?U`G1 z6-5+<6K;lUq69%fB`8W2Jn+twZ~kSUeY46c#S1DFpb`}&2nGTellXm;=~I0=J#*%A z!k8*n)vBJ;HJMqfd+(m^o!PCet(m=yePz36@yfu^m}(Bp&dwI?$@%jOwkwbCKC<1- zJe!JvNceu5!|*1YgKxw22aoRjOS>!R6+#M+#2=th=qfw|orN{HzPPaT3GJ?+^9)47 z57H=Jv6FC-u)5{Nw8E;jfn>xD8ROh=X#!`+*?CS_JuP~AqHzc%;o`*|_#EcMAA-lX zFUO$i2k;hQbtF79JhuxP%|ImF5wA!3hxkB_sZ+Ws5GGXGE`2$yRcZ>6F3`=@;^`$ zxkUaQp2OTm`8@B*g$G{+sL`|H58kmHRv?FY6 zx{mv`&51YOkMZIsWeB_r-A<${m;EMsNOtpQ5!S76Su`fB zlq1IVD*TO~hDB~Wu?fB3!Erft>1~B32Esjt!?EqlF&M{ZdHH=m^h)F%a;qY-5~2*iHB_7M>#XbD!Ie58y}84_u58POZ?!Kn#<3KZ4AK zO5rhrLH=d~{zz9Yxm%-?0R*hU%^<1`Vk7)CuX>@AfiA);&@}=^=>346=)I*L+CXo- zbOV0zqp!Y8XfF&s1KBM^8@zM_$pYY)xEF?=fleQ<7(*KvCI^y4>;q47z0k=3XN6)@ z*TqCIUmh=qF#uK(a0R~EbT%U4``{aNxx0(wieTL5iOyqd z0s2Rxs`g%O&cvEfyf=E-zW`HM_xzX_-}AYP3rmVNTs*|&4*f=e)bx&TLK6dRLdcTf zeQ4rYnQ&B7cv!iC`AdlR*&f~<)mZ#yDa^x=sYCp!Xc2wbGZ0cc82U=89xHkgd!`v8zx=`*WCvfaln^p#RV? zA-{u)@plSeqFLz-=Jr5VB&=3EWo9fQREABAtbu^Yh|{T&FN%(F_+o{H*-T3#nzU?U zb;2T8IxE78#dU;xPb1+0wFX3-+!(PWSak?-hC)J`?7^51@Flr87snA^9Prx+515$5 zJ~TX-7a5nKY;LT^P_#k}kvKOjt*7E$b}cO)>?2-GoPiWkSQ+;&kv~8aI))}RWMw;s zvtmhQ1>xpUXW;>@4Fp6+EW+L>eoV$3!i#@)^c5b^*+2}Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0`EygK~!i%?U}u6 z6hRoqS5Xj&T;wbws3<5X#4geJQHY(86zOaP3lST^*RLoFHU?3|voqM(2$m^S@E=eS zwGq+AB4}X*4?R>65#w)e-h-T(-JRLna8c(6yL->x&b-favv-@BB#}rY@-HHN)yn!A zj(hdQys=1+B_WI1ovv0UFIjD=H%9xCr1n8&sgxK%c3}LGia8KsjKfue{IX}tp@aZZ z!T4ttxe#Os4R@RXA2n^;(4!`Z_^h*Hq?`5kRUG`>4VR z#g1~Apx{q?#upi;@4G6T(DxAiK2e!UY5@BrO@{(2Dd7F{ITu;R?ifMZ9(uE>H>Ps$ z5a$J1<}tn%<1bZ~fcdjy^1X^Vk#LgaHOXL)(EdT%j07*qoM6N<$g7pi9SpWb4 literal 0 HcmV?d00001 diff --git a/client/battle/BattleFieldController.cpp b/client/battle/BattleFieldController.cpp index c11d82a93..dc943d653 100644 --- a/client/battle/BattleFieldController.cpp +++ b/client/battle/BattleFieldController.cpp @@ -43,6 +43,7 @@ BattleFieldController::BattleFieldController(BattleInterface & owner): //preparing cells and hexes cellBorder = IImage::createFromFile("CCELLGRD.BMP", EImageBlitMode::COLORKEY); + cellUnitMovementHighlight = IImage::createFromFile("CCNSSHD.BMP", EImageBlitMode::COLORKEY); cellShade = IImage::createFromFile("CCELLSHD.BMP"); if(!owner.siegeController) @@ -138,7 +139,6 @@ void BattleFieldController::showBackground(Canvas & canvas) showBackgroundImage(canvas); showHighlightedHexes(canvas); - } void BattleFieldController::showBackgroundImage(Canvas & canvas) @@ -172,32 +172,39 @@ void BattleFieldController::redrawBackgroundWithHexes() { const CStack *activeStack = owner.stacksController->getActiveStack(); std::vector attackableHexes; - if (activeStack) + if(activeStack) occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes); - //prepare background graphic with hexes and shaded hexes + auto accessibility = owner.curInt->cb->getAccesibility(); + + for(int i = 0; i < accessibility.size(); i++) + stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE); + + // 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 hexesToShade = occupyableHexes; hexesToShade.insert(hexesToShade.end(), attackableHexes.begin(), attackableHexes.end()); - for (BattleHex hex : hexesToShade) + for(BattleHex hex : hexesToShade) { backgroundWithHexes->draw(cellShade, hexPositionLocal(hex).topLeft()); } } + // draw cell borders if(settings["battle"]["cellBorders"].Bool()) { - for (int i=0; idraw(cellBorder, hexPositionLocal(i).topLeft()); @@ -205,7 +212,7 @@ void BattleFieldController::redrawBackgroundWithHexes() } } -void BattleFieldController::showHighlightedHex(Canvas & canvas, BattleHex hex, bool darkBorder) +void BattleFieldController::showShadedHex(Canvas & canvas, BattleHex hex, bool darkBorder) { Point hexPos = hexPositionLocal(hex).topLeft(); @@ -214,14 +221,23 @@ void BattleFieldController::showHighlightedHex(Canvas & canvas, BattleHex hex, b canvas.draw(cellBorder, hexPos); } -std::set BattleFieldController::getHighlightedHexesStackRange() +void BattleFieldController::showHighlightedHexForMovement(Canvas & canvas, BattleHex hex, bool darkBorder) +{ + Point hexPos = hexPositionLocal(hex).topLeft(); + + canvas.draw(cellUnitMovementHighlight, hexPos); + if(!darkBorder && settings["battle"]["cellBorders"].Bool()) + canvas.draw(cellBorder, hexPos); +} + +std::set BattleFieldController::getHighlightedHexesForActiveStack() { std::set 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,7 +246,22 @@ std::set BattleFieldController::getHighlightedHexesStackRange() for(BattleHex hex : set) result.insert(hex); - // display the movement shadow of stack under mouse + return result; +} + +std::set BattleFieldController::getMovementRangeForHoveredStack() +{ + std::set result; + + if (!owner.stacksController->getActiveStack()) + return result; + + if (!settings["battle"]["stackRange"].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()) { @@ -241,7 +272,7 @@ std::set BattleFieldController::getHighlightedHexesStackRange() return result; } -std::set BattleFieldController::getHighlightedHexesSpellRange() +std::set BattleFieldController::getHighlightedHexesForSpellRange() { std::set result; auto hoveredHex = getHoveredHex(); @@ -260,9 +291,9 @@ std::set 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 +307,74 @@ std::set BattleFieldController::getHighlightedHexesMovementTarget() const CStack * stack = owner.stacksController->getActiveStack(); auto hoveredHex = getHoveredHex(); - if (stack) + if(!stack) + return {}; + + std::vector availableHexes = owner.curInt->cb->battleGetAvailableHexes(stack, false, nullptr); + + auto hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true); + if(owner.curInt->cb->battleCanAttack(stack, hoveredStack, hoveredHex)) { - std::vector 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 hoveredStack = getHighlightedHexesStackRange(); - std::set hoveredSpell = getHighlightedHexesSpellRange(); - std::set hoveredMove = getHighlightedHexesMovementTarget(); + //std::set hoveredStack = getHighlightedHexesForActiveStack(); + std::set hoveredStackHexes = getMovementRangeForHoveredStack(); + std::set hoveredSpellHexes = getHighlightedHexesForSpellRange(); + std::set 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 background; std::shared_ptr cellBorder; + std::shared_ptr cellUnitMovementHighlight; std::shared_ptr cellShade; /// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack @@ -46,10 +47,12 @@ class BattleFieldController : public CIntObject /// hexes that when in front of a unit cause it's amount box to move back std::array stackCountOutsideHexes; - void showHighlightedHex(Canvas & to, BattleHex hex, bool darkBorder); + void showHighlightedHexForMovement(Canvas& canvas, BattleHex hex, bool darkBorder); + void showShadedHex(Canvas & to, BattleHex hex, bool darkBorder); - std::set getHighlightedHexesStackRange(); - std::set getHighlightedHexesSpellRange(); + std::set getHighlightedHexesForActiveStack(); + std::set getMovementRangeForHoveredStack(); + std::set getHighlightedHexesForSpellRange(); std::set getHighlightedHexesMovementTarget(); void showBackground(Canvas & canvas); From dab07bdef9e96c8b9316e92bf7386acd5f85c078 Mon Sep 17 00:00:00 2001 From: krs Date: Thu, 23 Mar 2023 23:03:18 +0200 Subject: [PATCH 2/9] Now unit range is shown in Tactics phase as well A new parameter: isActiveStack was needed in battleGetAvailableHexes, so that we show the propper Tactics range. --- AI/BattleAI/BattleAI.cpp | 2 +- AI/BattleAI/PotentialTargets.cpp | 2 +- AI/StupidAI/StupidAI.cpp | 4 ++-- client/battle/BattleActionsController.cpp | 4 ++-- client/battle/BattleFieldController.cpp | 8 +++---- lib/battle/CBattleInfoCallback.cpp | 27 ++++++++++------------- lib/battle/CBattleInfoCallback.h | 6 ++--- 7 files changed, 25 insertions(+), 28 deletions(-) diff --git a/AI/BattleAI/BattleAI.cpp b/AI/BattleAI/BattleAI.cpp index 595d88912..c5b0c581d 100644 --- a/AI/BattleAI/BattleAI.cpp +++ b/AI/BattleAI/BattleAI.cpp @@ -271,7 +271,7 @@ BattleAction CBattleAI::activeStack( const CStack * stack ) BattleAction CBattleAI::goTowardsNearest(const CStack * stack, std::vector 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 { diff --git a/AI/BattleAI/PotentialTargets.cpp b/AI/BattleAI/PotentialTargets.cpp index 5d4aac5e5..a817e8c30 100644 --- a/AI/BattleAI/PotentialTargets.cpp +++ b/AI/BattleAI/PotentialTargets.cpp @@ -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; diff --git a/AI/StupidAI/StupidAI.cpp b/AI/StupidAI/StupidAI.cpp index 2a8479f9e..cdfcc7bb5 100644 --- a/AI/StupidAI/StupidAI.cpp +++ b/AI/StupidAI/StupidAI.cpp @@ -120,7 +120,7 @@ BattleAction CStupidAI::activeStack( const CStack * stack ) } else { - std::vector avHexes = cb->battleGetAvailableHexes(stack); + std::vector 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 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 { diff --git a/client/battle/BattleActionsController.cpp b/client/battle/BattleActionsController.cpp index a3c47fd8f..f607fd0d2 100644 --- a/client/battle/BattleActionsController.cpp +++ b/client/battle/BattleActionsController.cpp @@ -623,7 +623,7 @@ void BattleActionsController::actionRealize(PossiblePlayerBattleAction action, B { if(owner.stacksController->getActiveStack()->doubleWide()) { - std::vector acc = owner.curInt->cb->battleGetAvailableHexes(owner.stacksController->getActiveStack()); + std::vector 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 acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove); + std::vector acc = owner.curInt->cb->battleGetAvailableHexes(stackToMove, false); BattleHex shiftedDest = myNumber.cloneInDirection(stackToMove->destShiftDir(), false); if (vstd::contains(acc, myNumber)) diff --git a/client/battle/BattleFieldController.cpp b/client/battle/BattleFieldController.cpp index dc943d653..b6f45044d 100644 --- a/client/battle/BattleFieldController.cpp +++ b/client/battle/BattleFieldController.cpp @@ -173,7 +173,7 @@ void BattleFieldController::redrawBackgroundWithHexes() const CStack *activeStack = owner.stacksController->getActiveStack(); std::vector attackableHexes; if(activeStack) - occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, &attackableHexes); + occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, true, &attackableHexes); auto accessibility = owner.curInt->cb->getAccesibility(); @@ -263,9 +263,9 @@ std::set BattleFieldController::getMovementRangeForHoveredStack() // 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 v = owner.curInt->cb->battleGetAvailableHexes(hoveredStack, true, nullptr); + std::vector v = owner.curInt->cb->battleGetAvailableHexes(hoveredStack, false, true, nullptr); for(BattleHex hex : v) result.insert(hex); } @@ -310,7 +310,7 @@ std::set BattleFieldController::getHighlightedHexesMovementTarget() if(!stack) return {}; - std::vector availableHexes = owner.curInt->cb->battleGetAvailableHexes(stack, false, nullptr); + std::vector 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)) diff --git a/lib/battle/CBattleInfoCallback.cpp b/lib/battle/CBattleInfoCallback.cpp index c9b205102..a056566f2 100644 --- a/lib/battle/CBattleInfoCallback.cpp +++ b/lib/battle/CBattleInfoCallback.cpp @@ -538,7 +538,7 @@ void CBattleInfoCallback::battleGetTurnOrder(std::vector & turns, battleGetTurnOrder(turns, maxUnits, maxTurns, actualTurn + 1, sideThatLastMoved); } -std::vector CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit) const +std::vector CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack) const { RETURN_IF_NOT_BATTLE(std::vector()); @@ -547,10 +547,10 @@ std::vector CBattleInfoCallback::battleGetAvailableHexes(const battle auto reachability = getReachability(unit); - return battleGetAvailableHexes(reachability, unit); + return battleGetAvailableHexes(reachability, unit, isActiveStack); } -std::vector CBattleInfoCallback::battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit) const +std::vector CBattleInfoCallback::battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit, bool isActiveStack) const { std::vector ret; @@ -560,7 +560,7 @@ std::vector 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 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(unitSpeed)) continue; } @@ -587,10 +587,9 @@ std::vector CBattleInfoCallback::battleGetAvailableHexes(const Reacha return ret; } - -std::vector CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit, bool addOccupiable, std::vector * attackable) const +std::vector CBattleInfoCallback::battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack, bool addOccupiable, std::vector * attackable) const { - std::vector ret = battleGetAvailableHexes(unit); + std::vector 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 & obstacles, @@ -1030,7 +1028,7 @@ std::set CBattleInfoCallback::getStoppers(BattlePerspective::BattlePe std::pair 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; diff --git a/lib/battle/CBattleInfoCallback.h b/lib/battle/CBattleInfoCallback.h index 1adcbf8c8..4de572310 100644 --- a/lib/battle/CBattleInfoCallback.h +++ b/lib/battle/CBattleInfoCallback.h @@ -74,12 +74,12 @@ public: void battleGetTurnOrder(std::vector & 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 battleGetAvailableHexes(const battle::Unit * unit, bool addOccupiable, std::vector * attackable) const; + std::vector battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack, bool addOccupiable, std::vector * attackable) const; ///returns reachable hexes (valid movement destinations), DOES contain stack current position (lite version) - std::vector battleGetAvailableHexes(const battle::Unit * unit) const; + std::vector battleGetAvailableHexes(const battle::Unit * unit, bool isActiveStack) const; - std::vector battleGetAvailableHexes(const ReachabilityInfo & cache, const battle::Unit * unit) const; + std::vector 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; From 51ad49532b50ebe928051956016e46f70a725022 Mon Sep 17 00:00:00 2001 From: krs Date: Tue, 4 Apr 2023 21:41:48 +0300 Subject: [PATCH 3/9] Fix for wrong merge :( --- client/battle/BattleFieldController.cpp | 6 ------ 1 file changed, 6 deletions(-) diff --git a/client/battle/BattleFieldController.cpp b/client/battle/BattleFieldController.cpp index b6f45044d..2de20d000 100644 --- a/client/battle/BattleFieldController.cpp +++ b/client/battle/BattleFieldController.cpp @@ -175,11 +175,6 @@ void BattleFieldController::redrawBackgroundWithHexes() if(activeStack) occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, true, &attackableHexes); - auto accessibility = owner.curInt->cb->getAccesibility(); - - for(int i = 0; i < accessibility.size(); i++) - stackCountOutsideHexes[i] = (accessibility[i] == EAccessibility::ACCESSIBLE); - // prepare background graphic with hexes and shaded hexes backgroundWithHexes->draw(background, Point(0,0)); owner.obstacleController->showAbsoluteObstacles(*backgroundWithHexes); @@ -348,7 +343,6 @@ std::set BattleFieldController::getHighlightedHexesMovementTarget() void BattleFieldController::showHighlightedHexes(Canvas & canvas) { - //std::set hoveredStack = getHighlightedHexesForActiveStack(); std::set hoveredStackHexes = getMovementRangeForHoveredStack(); std::set hoveredSpellHexes = getHighlightedHexesForSpellRange(); std::set hoveredMoveHexes = getHighlightedHexesMovementTarget(); From 9012a25276ae20940d5d0bb21d3ca9f6d68f3e9b Mon Sep 17 00:00:00 2001 From: krs Date: Tue, 4 Apr 2023 22:34:56 +0300 Subject: [PATCH 4/9] Stub For Max Movement Range highlight When a creature is hovered., besides movement, for max possible movement, a hex in center of map is now highlighted. --- Mods/vcmi/Data/CCNSSh2.png | Bin 1370 -> 0 bytes Mods/vcmi/Data/CCNSShd.png | Bin 858 -> 0 bytes Mods/vcmi/Data/UnitMaxMovementHighlight.png | Bin 0 -> 422 bytes Mods/vcmi/Data/UnitMovementHighlight.png | Bin 0 -> 272 bytes client/battle/BattleFieldController.cpp | 69 +++++++++++++------- client/battle/BattleFieldController.h | 5 +- 6 files changed, 48 insertions(+), 26 deletions(-) delete mode 100644 Mods/vcmi/Data/CCNSSh2.png delete mode 100644 Mods/vcmi/Data/CCNSShd.png create mode 100644 Mods/vcmi/Data/UnitMaxMovementHighlight.png create mode 100644 Mods/vcmi/Data/UnitMovementHighlight.png diff --git a/Mods/vcmi/Data/CCNSSh2.png b/Mods/vcmi/Data/CCNSSh2.png deleted file mode 100644 index 2685b035135a0a20325776698e248c234abbe78e..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 1370 zcmV-g1*Q6lP)Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!2kdb!2!6DYwZ941n)^iK~!i%?U`G1 z6-5+<6K;lUq69%fB`8W2Jn+twZ~kSUeY46c#S1DFpb`}&2nGTellXm;=~I0=J#*%A z!k8*n)vBJ;HJMqfd+(m^o!PCet(m=yePz36@yfu^m}(Bp&dwI?$@%jOwkwbCKC<1- zJe!JvNceu5!|*1YgKxw22aoRjOS>!R6+#M+#2=th=qfw|orN{HzPPaT3GJ?+^9)47 z57H=Jv6FC-u)5{Nw8E;jfn>xD8ROh=X#!`+*?CS_JuP~AqHzc%;o`*|_#EcMAA-lX zFUO$i2k;hQbtF79JhuxP%|ImF5wA!3hxkB_sZ+Ws5GGXGE`2$yRcZ>6F3`=@;^`$ zxkUaQp2OTm`8@B*g$G{+sL`|H58kmHRv?FY6 zx{mv`&51YOkMZIsWeB_r-A<${m;EMsNOtpQ5!S76Su`fB zlq1IVD*TO~hDB~Wu?fB3!Erft>1~B32Esjt!?EqlF&M{ZdHH=m^h)F%a;qY-5~2*iHB_7M>#XbD!Ie58y}84_u58POZ?!Kn#<3KZ4AK zO5rhrLH=d~{zz9Yxm%-?0R*hU%^<1`Vk7)CuX>@AfiA);&@}=^=>346=)I*L+CXo- zbOV0zqp!Y8XfF&s1KBM^8@zM_$pYY)xEF?=fleQ<7(*KvCI^y4>;q47z0k=3XN6)@ z*TqCIUmh=qF#uK(a0R~EbT%U4``{aNxx0(wieTL5iOyqd z0s2Rxs`g%O&cvEfyf=E-zW`HM_xzX_-}AYP3rmVNTs*|&4*f=e)bx&TLK6dRLdcTf zeQ4rYnQ&B7cv!iC`AdlR*&f~<)mZ#yDa^x=sYCp!Xc2wbGZ0cc82U=89xHkgd!`v8zx=`*WCvfaln^p#RV? zA-{u)@plSeqFLz-=Jr5VB&=3EWo9fQREABAtbu^Yh|{T&FN%(F_+o{H*-T3#nzU?U zb;2T8IxE78#dU;xPb1+0wFX3-+!(PWSak?-hC)J`?7^51@Flr87snA^9Prx+515$5 zJ~TX-7a5nKY;LT^P_#k}kvKOjt*7E$b}cO)>?2-GoPiWkSQ+;&kv~8aI))}RWMw;s zvtmhQ1>xpUXW;>@4Fp6+EW+L>eoV$3!i#@)^c5b^*+2}Px#1ZP1_K>z@;j|==^1poj532;bRa{vGi!vFvd!vV){sAK>D0`EygK~!i%?U}u6 z6hRoqS5Xj&T;wbws3<5X#4geJQHY(86zOaP3lST^*RLoFHU?3|voqM(2$m^S@E=eS zwGq+AB4}X*4?R>65#w)e-h-T(-JRLna8c(6yL->x&b-favv-@BB#}rY@-HHN)yn!A zj(hdQys=1+B_WI1ovv0UFIjD=H%9xCr1n8&sgxK%c3}LGia8KsjKfue{IX}tp@aZZ z!T4ttxe#Os4R@RXA2n^;(4!`Z_^h*Hq?`5kRUG`>4VR z#g1~Apx{q?#upi;@4G6T(DxAiK2e!UY5@BrO@{(2Dd7F{ITu;R?ifMZ9(uE>H>Ps$ z5a$J1<}tn%<1bZ~fcdjy^1X^Vk#LgaHOXL)(EdT%j07*qoM6N<$g7pi9SpWb4 diff --git a/Mods/vcmi/Data/UnitMaxMovementHighlight.png b/Mods/vcmi/Data/UnitMaxMovementHighlight.png new file mode 100644 index 0000000000000000000000000000000000000000..1ed74dda43db741f6cda3fd1644694809812b9ea GIT binary patch literal 422 zcmV;X0a^ZuP)cN80004PNkl$}R5CIX@rI^0qg;DL#O#i{g zKm4AN?9PWE@6An&adZ({XrZqW?d#t1;W)x?2{$753e-@)|uK zmL~=tf!`1|9i9-5$*~WY-*c*I{{w%vEbaLz!u$Ef=;$fN<^lMVWnu4|{DP03YIGI0 z0DrJNUhrvA(7uKmYytjgp`)W`jd*gfO-J(sC{wAq)VEM+lT*4erucse)$- z!x|2LodI~*>mNX3{O+Hl-W|YdsLsE>82?3)uHvdK|85|j4J2iN~(n^DVPTx`6#L@??_y$g5j{mY-%O>KDB zf7kX}%KP5*q~6x$2{(VNzR{lkRbs-{ZwnVjzj?E3# T%9joRdXd4?)z4*}Q$iB}fUk4L literal 0 HcmV?d00001 diff --git a/client/battle/BattleFieldController.cpp b/client/battle/BattleFieldController.cpp index 2de20d000..7eff5ed2b 100644 --- a/client/battle/BattleFieldController.cpp +++ b/client/battle/BattleFieldController.cpp @@ -43,8 +43,9 @@ BattleFieldController::BattleFieldController(BattleInterface & owner): //preparing cells and hexes cellBorder = IImage::createFromFile("CCELLGRD.BMP", EImageBlitMode::COLORKEY); - cellUnitMovementHighlight = IImage::createFromFile("CCNSSHD.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) { @@ -181,7 +182,7 @@ void BattleFieldController::redrawBackgroundWithHexes() if(owner.siegeController) owner.siegeController->showAbsoluteObstacles(*backgroundWithHexes); - // show shaded hexes for active's stack valid movement and the hexes that it can attack + // show shaded hexes for active's stackMovement valid movement and the hexes that it can attack if(settings["battle"]["stackRange"].Bool()) { std::vector hexesToShade = occupyableHexes; @@ -207,20 +208,11 @@ void BattleFieldController::redrawBackgroundWithHexes() } } -void BattleFieldController::showShadedHex(Canvas & canvas, BattleHex hex, bool darkBorder) +void BattleFieldController::showHighlightedHex(Canvas & canvas, std::shared_ptr highlight, BattleHex hex, bool darkBorder) { Point hexPos = hexPositionLocal(hex).topLeft(); - canvas.draw(cellShade, hexPos); - if(!darkBorder && settings["battle"]["cellBorders"].Bool()) - canvas.draw(cellBorder, hexPos); -} - -void BattleFieldController::showHighlightedHexForMovement(Canvas & canvas, BattleHex hex, bool darkBorder) -{ - Point hexPos = hexPositionLocal(hex).topLeft(); - - canvas.draw(cellUnitMovementHighlight, hexPos); + canvas.draw(highlight, hexPos); if(!darkBorder && settings["battle"]["cellBorders"].Bool()) canvas.draw(cellBorder, hexPos); } @@ -267,6 +259,31 @@ std::set BattleFieldController::getMovementRangeForHoveredStack() return result; } +std::set BattleFieldController::STUB_getMaxMovementRangeForHoveredStack() +{ + std::set result; + + if (!owner.stacksController->getActiveStack()) + return result; + + if (!settings["battle"]["stackRange"].Bool()) + return result; + + auto hoveredHex = getHoveredHex(); + + // add max movement hexes for stack under mouse + const CStack * const hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true); + if(hoveredStack) + { + auto hex = BattleHex(10, 5); + + result.insert(hex); + } + + return result; + +} + std::set BattleFieldController::getHighlightedHexesForSpellRange() { std::set result; @@ -343,7 +360,8 @@ std::set BattleFieldController::getHighlightedHexesMovementTarget() void BattleFieldController::showHighlightedHexes(Canvas & canvas) { - std::set hoveredStackHexes = getMovementRangeForHoveredStack(); + std::set hoveredStackMovementRangeHexes = getMovementRangeForHoveredStack(); + std::set hoveredStackMaxMovementHexes = STUB_getMaxMovementRangeForHoveredStack(); std::set hoveredSpellHexes = getHighlightedHexesForSpellRange(); std::set hoveredMoveHexes = getHighlightedHexesMovementTarget(); @@ -352,24 +370,27 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas) auto const & hoveredMouseHexes = owner.actionsController->currentActionSpellcasting(getHoveredHex()) ? hoveredSpellHexes : hoveredMoveHexes; - for(int b=0; b background; std::shared_ptr cellBorder; std::shared_ptr cellUnitMovementHighlight; + std::shared_ptr cellUnitMaxMovementHighlight; std::shared_ptr cellShade; /// Canvas that contains background, hex grid (if enabled), absolute obstacles and movement range of active stack @@ -47,11 +48,11 @@ class BattleFieldController : public CIntObject /// hexes that when in front of a unit cause it's amount box to move back std::array stackCountOutsideHexes; - void showHighlightedHexForMovement(Canvas& canvas, BattleHex hex, bool darkBorder); - void showShadedHex(Canvas & to, BattleHex hex, bool darkBorder); + void showHighlightedHex(Canvas & to, std::shared_ptr highlight, BattleHex hex, bool darkBorder); std::set getHighlightedHexesForActiveStack(); std::set getMovementRangeForHoveredStack(); + std::set STUB_getMaxMovementRangeForHoveredStack(); std::set getHighlightedHexesForSpellRange(); std::set getHighlightedHexesMovementTarget(); From 1644cab9380056773dcdb51304ba33282a1c4b71 Mon Sep 17 00:00:00 2001 From: krs Date: Thu, 6 Apr 2023 00:04:40 +0300 Subject: [PATCH 5/9] Added combat option Highlight Movement on Hover --- Mods/vcmi/config/vcmi/english.json | 2 ++ Mods/vcmi/mod.json | 1 + client/battle/BattleFieldController.cpp | 24 +++++++++---------- client/battle/BattleFieldController.h | 2 +- client/windows/settings/BattleOptionsTab.cpp | 15 ++++++++++++ client/windows/settings/BattleOptionsTab.h | 1 + config/widgets/settings/battleOptionsTab.json | 22 +++++++++++++---- 7 files changed, 49 insertions(+), 18 deletions(-) diff --git a/Mods/vcmi/config/vcmi/english.json b/Mods/vcmi/config/vcmi/english.json index 2c366799a..cc60502a6 100644 --- a/Mods/vcmi/config/vcmi/english.json +++ b/Mods/vcmi/config/vcmi/english.json @@ -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", diff --git a/Mods/vcmi/mod.json b/Mods/vcmi/mod.json index e24f67a5c..0b6172847 100644 --- a/Mods/vcmi/mod.json +++ b/Mods/vcmi/mod.json @@ -50,6 +50,7 @@ "description" : "Ключові файли необхідні для повноцінної роботи VCMI", "author" : "Команда VCMI", + "skipValidation" : true, "translations" : [ "config/vcmi/ukrainian.json" ] diff --git a/client/battle/BattleFieldController.cpp b/client/battle/BattleFieldController.cpp index 7eff5ed2b..f7ad4e2d5 100644 --- a/client/battle/BattleFieldController.cpp +++ b/client/battle/BattleFieldController.cpp @@ -174,7 +174,7 @@ void BattleFieldController::redrawBackgroundWithHexes() const CStack *activeStack = owner.stacksController->getActiveStack(); std::vector attackableHexes; if(activeStack) - occupyableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, true, &attackableHexes); + occupiableHexes = owner.curInt->cb->battleGetAvailableHexes(activeStack, true, true, &attackableHexes); // prepare background graphic with hexes and shaded hexes backgroundWithHexes->draw(background, Point(0,0)); @@ -182,14 +182,14 @@ void BattleFieldController::redrawBackgroundWithHexes() if(owner.siegeController) owner.siegeController->showAbsoluteObstacles(*backgroundWithHexes); - // show shaded hexes for active's stackMovement valid movement and the hexes that it can attack + // show shaded hexes for active's stack valid movement and the hexes that it can attack if(settings["battle"]["stackRange"].Bool()) { - std::vector hexesToShade = occupyableHexes; + std::vector hexesToShade = occupiableHexes; hexesToShade.insert(hexesToShade.end(), attackableHexes.begin(), attackableHexes.end()); for(BattleHex hex : hexesToShade) { - backgroundWithHexes->draw(cellShade, hexPositionLocal(hex).topLeft()); + showHighlightedHex(*backgroundWithHexes, cellShade, hex, false); } } @@ -243,7 +243,7 @@ std::set BattleFieldController::getMovementRangeForHoveredStack() if (!owner.stacksController->getActiveStack()) return result; - if (!settings["battle"]["stackRange"].Bool()) + if (!settings["battle"]["movementHighlightOnHover"].Bool()) return result; auto hoveredHex = getHoveredHex(); @@ -266,7 +266,7 @@ std::set BattleFieldController::STUB_getMaxMovementRangeForHoveredSta if (!owner.stacksController->getActiveStack()) return result; - if (!settings["battle"]["stackRange"].Bool()) + if (!settings["battle"]["movementHighlightOnHover"].Bool()) return result; auto hoveredHex = getHoveredHex(); @@ -486,18 +486,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; @@ -609,7 +609,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; diff --git a/client/battle/BattleFieldController.h b/client/battle/BattleFieldController.h index 4487513ad..94ed04860 100644 --- a/client/battle/BattleFieldController.h +++ b/client/battle/BattleFieldController.h @@ -43,7 +43,7 @@ class BattleFieldController : public CIntObject BattleHex attackingHex; /// hexes to which currently active stack can move - std::vector occupyableHexes; + std::vector occupiableHexes; /// hexes that when in front of a unit cause it's amount box to move back std::array stackCountOutsideHexes; diff --git a/client/windows/settings/BattleOptionsTab.cpp b/client/windows/settings/BattleOptionsTab.cpp index 69a4ffa22..c2992b3b4 100644 --- a/client/windows/settings/BattleOptionsTab.cpp +++ b/client/windows/settings/BattleOptionsTab.cpp @@ -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 movementShadowCheckbox = widget("movementShadowCheckbox"); movementShadowCheckbox->setSelected(settings["battle"]["stackRange"].Bool()); + std::shared_ptr movementHighlightOnHoverCheckbox = widget("movementHighlightOnHoverCheckbox"); + movementHighlightOnHoverCheckbox->setSelected(settings["battle"]["movementHighlightOnHover"].Bool()); + std::shared_ptr mouseShadowCheckbox = widget("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"]; diff --git a/client/windows/settings/BattleOptionsTab.h b/client/windows/settings/BattleOptionsTab.h index 77ef5e293..2afb7d958 100644 --- a/client/windows/settings/BattleOptionsTab.h +++ b/client/windows/settings/BattleOptionsTab.h @@ -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); diff --git a/config/widgets/settings/battleOptionsTab.json b/config/widgets/settings/battleOptionsTab.json index 95bcd0d52..708ee1f2f 100644 --- a/config/widgets/settings/battleOptionsTab.json +++ b/config/widgets/settings/battleOptionsTab.json @@ -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" }, { From aba5840a6fb5d945c5f8e6eef1eb57644cd59bf5 Mon Sep 17 00:00:00 2001 From: krs Date: Thu, 6 Apr 2023 00:12:42 +0300 Subject: [PATCH 6/9] Removed Max Movement Highlight stubs --- client/battle/BattleFieldController.cpp | 29 ------------------------- client/battle/BattleFieldController.h | 1 - 2 files changed, 30 deletions(-) diff --git a/client/battle/BattleFieldController.cpp b/client/battle/BattleFieldController.cpp index f7ad4e2d5..be67b14ea 100644 --- a/client/battle/BattleFieldController.cpp +++ b/client/battle/BattleFieldController.cpp @@ -259,31 +259,6 @@ std::set BattleFieldController::getMovementRangeForHoveredStack() return result; } -std::set BattleFieldController::STUB_getMaxMovementRangeForHoveredStack() -{ - std::set result; - - if (!owner.stacksController->getActiveStack()) - return result; - - if (!settings["battle"]["movementHighlightOnHover"].Bool()) - return result; - - auto hoveredHex = getHoveredHex(); - - // add max movement hexes for stack under mouse - const CStack * const hoveredStack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true); - if(hoveredStack) - { - auto hex = BattleHex(10, 5); - - result.insert(hex); - } - - return result; - -} - std::set BattleFieldController::getHighlightedHexesForSpellRange() { std::set result; @@ -361,7 +336,6 @@ std::set BattleFieldController::getHighlightedHexesMovementTarget() void BattleFieldController::showHighlightedHexes(Canvas & canvas) { std::set hoveredStackMovementRangeHexes = getMovementRangeForHoveredStack(); - std::set hoveredStackMaxMovementHexes = STUB_getMaxMovementRangeForHoveredStack(); std::set hoveredSpellHexes = getHighlightedHexesForSpellRange(); std::set hoveredMoveHexes = getHighlightedHexesMovementTarget(); @@ -373,7 +347,6 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas) for(int hex = 0; hex < GameConstants::BFIELD_SIZE; ++hex) { bool stackMovement = hoveredStackMovementRangeHexes.count(hex); - bool stackMaxMovement = hoveredStackMaxMovementHexes.count(hex); bool mouse = hoveredMouseHexes.count(hex); if(stackMovement && mouse) // area where hovered stackMovement can move shown with highlight. Because also affected by mouse cursor, shade as well @@ -389,8 +362,6 @@ void BattleFieldController::showHighlightedHexes(Canvas & canvas) { showHighlightedHex(canvas, cellUnitMovementHighlight, hex, false); } - if(stackMaxMovement) - showHighlightedHex(canvas, cellUnitMaxMovementHighlight, hex, false); } } diff --git a/client/battle/BattleFieldController.h b/client/battle/BattleFieldController.h index 94ed04860..1697e75e5 100644 --- a/client/battle/BattleFieldController.h +++ b/client/battle/BattleFieldController.h @@ -52,7 +52,6 @@ class BattleFieldController : public CIntObject std::set getHighlightedHexesForActiveStack(); std::set getMovementRangeForHoveredStack(); - std::set STUB_getMaxMovementRangeForHoveredStack(); std::set getHighlightedHexesForSpellRange(); std::set getHighlightedHexesMovementTarget(); From 709a8a6eb3c3686630c3b3ac0001cbe2555e1fb9 Mon Sep 17 00:00:00 2001 From: krs Date: Thu, 6 Apr 2023 00:22:58 +0300 Subject: [PATCH 7/9] movementHighlightOnHover is now saved with settings --- config/schemas/settings.json | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/config/schemas/settings.json b/config/schemas/settings.json index 1d8710464..0bcea1429 100644 --- a/config/schemas/settings.json +++ b/config/schemas/settings.json @@ -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 From 31949998097799f747229803c18d3c42cc68d8e0 Mon Sep 17 00:00:00 2001 From: krs Date: Fri, 7 Apr 2023 00:29:58 +0300 Subject: [PATCH 8/9] Add SHIFT + hover shortcut to show movement highlight while pressed. --- client/battle/BattleWindow.cpp | 17 +++++++++++++++++ client/battle/BattleWindow.h | 4 ++++ client/gui/CGuiHandler.cpp | 2 +- 3 files changed, 22 insertions(+), 1 deletion(-) diff --git a/client/battle/BattleWindow.cpp b/client/battle/BattleWindow.cpp index 381523c69..310665219 100644 --- a/client/battle/BattleWindow.cpp +++ b/client/battle/BattleWindow.cpp @@ -198,6 +198,23 @@ void BattleWindow::keyPressed(const SDL_Keycode & key) { owner.actionsController->endCastingSpell(); } + else if(key == SDLK_LSHIFT) + { + // save and activate setting + Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"]; + movementHighlightOnHoverCache = movementHighlightOnHover->Bool(); + movementHighlightOnHover->Bool() = true; + } +} + +void BattleWindow::keyReleased(const SDL_Keycode & key) +{ + if(key == SDLK_LSHIFT) + { + // set back to initial state + Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"]; + movementHighlightOnHover->Bool() = movementHighlightOnHoverCache; + } } void BattleWindow::clickRight(tribool down, bool previousState) diff --git a/client/battle/BattleWindow.h b/client/battle/BattleWindow.h index afc4ff4af..3b03c78f5 100644 --- a/client/battle/BattleWindow.h +++ b/client/battle/BattleWindow.h @@ -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 &); +private: + /// used to save the state of this setting on toggle. + bool movementHighlightOnHoverCache; }; diff --git a/client/gui/CGuiHandler.cpp b/client/gui/CGuiHandler.cpp index 3135104fe..4063d5890 100644 --- a/client/gui/CGuiHandler.cpp +++ b/client/gui/CGuiHandler.cpp @@ -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); From 7eda4b6c1e1722d52862c99acfc7bf41d53a8a5e Mon Sep 17 00:00:00 2001 From: krs Date: Fri, 7 Apr 2023 22:06:57 +0300 Subject: [PATCH 9/9] replaced SDLK_LSHIFT check with GH.isKeyboardShiftDown() --- client/battle/BattleWindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/client/battle/BattleWindow.cpp b/client/battle/BattleWindow.cpp index 310665219..490e6b590 100644 --- a/client/battle/BattleWindow.cpp +++ b/client/battle/BattleWindow.cpp @@ -198,7 +198,7 @@ void BattleWindow::keyPressed(const SDL_Keycode & key) { owner.actionsController->endCastingSpell(); } - else if(key == SDLK_LSHIFT) + else if(GH.isKeyboardShiftDown()) { // save and activate setting Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"]; @@ -209,7 +209,7 @@ void BattleWindow::keyPressed(const SDL_Keycode & key) void BattleWindow::keyReleased(const SDL_Keycode & key) { - if(key == SDLK_LSHIFT) + if(!GH.isKeyboardShiftDown()) { // set back to initial state Settings movementHighlightOnHover = settings.write["battle"]["movementHighlightOnHover"];