1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-11-25 22:42:04 +02:00

Fixes #1051, #1042 - highlight creatures that will be affected by spell

This commit is contained in:
Ivan Savenko
2022-12-17 00:10:12 +02:00
parent 4d5311789e
commit 70eac47f08
4 changed files with 100 additions and 45 deletions

View File

@@ -263,9 +263,6 @@ void BattleActionsController::handleHex(BattleHex myNumber, int eventType)
if (shere) if (shere)
ourStack = shere->owner == owner.curInt->playerID; ourStack = shere->owner == owner.curInt->playerID;
//stack may have changed, update selection border
owner.stacksController->setHoveredStack(shere);
localActions.clear(); localActions.clear();
illegalActions.clear(); illegalActions.clear();

View File

@@ -902,7 +902,7 @@ void BattleInterface::show(SDL_Surface *to)
fieldController->renderBattlefield(canvas); fieldController->renderBattlefield(canvas);
stacksController->updateBattleAnimations(); stacksController->update();
SDL_SetClipRect(to, &buf); //restoring previous clip_rect SDL_SetClipRect(to, &buf); //restoring previous clip_rect

View File

@@ -13,6 +13,7 @@
#include "BattleSiegeController.h" #include "BattleSiegeController.h"
#include "BattleInterfaceClasses.h" #include "BattleInterfaceClasses.h"
#include "BattleInterface.h" #include "BattleInterface.h"
#include "BattleActionsController.h"
#include "BattleAnimationClasses.h" #include "BattleAnimationClasses.h"
#include "BattleFieldController.h" #include "BattleFieldController.h"
#include "BattleEffectsController.h" #include "BattleEffectsController.h"
@@ -27,6 +28,7 @@
#include "../gui/CAnimation.h" #include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h" #include "../gui/CGuiHandler.h"
#include "../gui/Canvas.h" #include "../gui/Canvas.h"
#include "../../lib/spells/ISpellMechanics.h"
#include "../../CCallback.h" #include "../../CCallback.h"
#include "../../lib/battle/BattleHex.h" #include "../../lib/battle/BattleHex.h"
@@ -69,7 +71,6 @@ static void onAnimationFinished(const CStack *stack, std::weak_ptr<CreatureAnima
BattleStacksController::BattleStacksController(BattleInterface & owner): BattleStacksController::BattleStacksController(BattleInterface & owner):
owner(owner), owner(owner),
activeStack(nullptr), activeStack(nullptr),
mouseHoveredStack(nullptr),
stackToActivate(nullptr), stackToActivate(nullptr),
selectedStack(nullptr), selectedStack(nullptr),
stackCanCastSpell(false), stackCanCastSpell(false),
@@ -242,30 +243,6 @@ void BattleStacksController::setActiveStack(const CStack *stack)
owner.controlPanel->blockUI(activeStack == nullptr); owner.controlPanel->blockUI(activeStack == nullptr);
} }
void BattleStacksController::setHoveredStack(const CStack *stack)
{
if ( stack == mouseHoveredStack )
return;
if (mouseHoveredStack)
stackAnimation[mouseHoveredStack->ID]->setBorderColor(AnimationControls::getNoBorder());
// stack must be alive and not active (which uses gold border instead)
if (stack && stack->alive() && stack != activeStack)
{
mouseHoveredStack = stack;
if (mouseHoveredStack && !mouseHoveredStack->isFrozen())
{
stackAnimation[mouseHoveredStack->ID]->setBorderColor(AnimationControls::getBlueBorder());
if (stackAnimation[mouseHoveredStack->ID]->framesInGroup(ECreatureAnimType::MOUSEON) > 0)
stackAnimation[mouseHoveredStack->ID]->playOnce(ECreatureAnimType::MOUSEON);
}
}
else
mouseHoveredStack = nullptr;
}
bool BattleStacksController::stackNeedsAmountBox(const CStack * stack) const bool BattleStacksController::stackNeedsAmountBox(const CStack * stack) const
{ {
BattleHex currentActionTarget; BattleHex currentActionTarget;
@@ -279,9 +256,6 @@ bool BattleStacksController::stackNeedsAmountBox(const CStack * stack) const
if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->getCount() == 1) //do not show box for singular war machines, stacked war machines with box shown are supported as extension feature if(stack->hasBonusOfType(Bonus::SIEGE_WEAPON) && stack->getCount() == 1) //do not show box for singular war machines, stacked war machines with box shown are supported as extension feature
return false; return false;
if (!owner.battleActionsStarted) // do not perform any further checks since they are related to actions that will only occur after intro music
return true;
if(!stack->alive()) if(!stack->alive())
return false; return false;
@@ -377,6 +351,12 @@ void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
stackAnimation[stack->ID]->incrementFrame(float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000); stackAnimation[stack->ID]->incrementFrame(float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000);
} }
void BattleStacksController::update()
{
updateHoveredStacks();
updateBattleAnimations();
}
void BattleStacksController::updateBattleAnimations() void BattleStacksController::updateBattleAnimations()
{ {
for (auto & elem : currentAnimations) for (auto & elem : currentAnimations)
@@ -390,7 +370,6 @@ void BattleStacksController::updateBattleAnimations()
elem->tryInitialize(); elem->tryInitialize();
} }
bool hadAnimations = !currentAnimations.empty(); bool hadAnimations = !currentAnimations.empty();
vstd::erase(currentAnimations, nullptr); vstd::erase(currentAnimations, nullptr);
@@ -674,7 +653,6 @@ void BattleStacksController::endAction(const BattleAction* action)
void BattleStacksController::startAction(const BattleAction* action) void BattleStacksController::startAction(const BattleAction* action)
{ {
setHoveredStack(nullptr);
removeExpiredColorFilters(); removeExpiredColorFilters();
} }
@@ -819,3 +797,77 @@ void BattleStacksController::removeExpiredColorFilters()
return true; return true;
}); });
} }
void BattleStacksController::updateHoveredStacks()
{
auto newStacks = selectHoveredStacks();
for (auto const * stack : mouseHoveredStacks)
{
if (vstd::contains(newStacks, stack))
continue;
if (stack == activeStack)
stackAnimation[stack->ID]->setBorderColor(AnimationControls::getGoldBorder());
else
stackAnimation[stack->ID]->setBorderColor(AnimationControls::getNoBorder());
}
for (auto const * stack : newStacks)
{
if (vstd::contains(mouseHoveredStacks, stack))
continue;
stackAnimation[stack->ID]->setBorderColor(AnimationControls::getBlueBorder());
if (stackAnimation[stack->ID]->framesInGroup(ECreatureAnimType::MOUSEON) > 0)
stackAnimation[stack->ID]->playOnce(ECreatureAnimType::MOUSEON);
}
mouseHoveredStacks = newStacks;
}
std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
{
auto hoveredHex = owner.fieldController->getHoveredHex();
if (!hoveredHex.isValid())
return {};
const spells::Caster *caster = nullptr;
const CSpell *spell = nullptr;
spells::Mode mode = spells::Mode::HERO;
if(owner.actionsController->spellcastingModeActive())//hero casts spell
{
spell = owner.actionsController->selectedSpell().toSpell();
caster = owner.getActiveHero();
}
else if(owner.stacksController->activeStackSpellToCast() != SpellID::NONE)//stack casts spell
{
spell = SpellID(owner.stacksController->activeStackSpellToCast()).toSpell();
caster = owner.stacksController->getActiveStack();
mode = spells::Mode::CREATURE_ACTIVE;
}
if(caster && spell) //when casting spell
{
spells::Target target;
target.emplace_back(hoveredHex);
spells::BattleCast event(owner.curInt->cb.get(), caster, mode, spell);
auto mechanics = spell->battleMechanics(&event);
return mechanics->getAffectedStacks(target);
}
if(hoveredHex.isValid())
{
const CStack * const stack = owner.curInt->cb->battleGetStackByPos(hoveredHex, true);
if (stack)
return {stack};
}
return {};
}

View File

@@ -70,8 +70,8 @@ class BattleStacksController
/// currently active stack; nullptr - no one /// currently active stack; nullptr - no one
const CStack *activeStack; const CStack *activeStack;
/// stack below mouse pointer, used for border animation /// stacks below mouse pointer (multiple stacks possible while spellcasting), used for border animation
const CStack *mouseHoveredStack; std::vector<const CStack *> mouseHoveredStacks;
///when animation is playing, we should wait till the end to make the next stack active; nullptr of none ///when animation is playing, we should wait till the end to make the next stack active; nullptr of none
const CStack *stackToActivate; const CStack *stackToActivate;
@@ -94,6 +94,12 @@ class BattleStacksController
void executeAttackAnimations(); void executeAttackAnimations();
void removeExpiredColorFilters(); void removeExpiredColorFilters();
void updateBattleAnimations();
void updateHoveredStacks();
std::vector<const CStack *> selectHoveredStacks();
public: public:
BattleStacksController(BattleInterface & owner); BattleStacksController(BattleInterface & owner);
@@ -117,7 +123,6 @@ public:
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
void setActiveStack(const CStack *stack); void setActiveStack(const CStack *stack);
void setHoveredStack(const CStack *stack);
void setSelectedStack(const CStack *stack); void setSelectedStack(const CStack *stack);
void showAliveStack(Canvas & canvas, const CStack * stack); void showAliveStack(Canvas & canvas, const CStack * stack);
@@ -130,11 +135,12 @@ public:
/// If effect from same (target, source) already exists, it will be updated /// If effect from same (target, source) already exists, it will be updated
void setStackColorFilter(const ColorFilter & effect, const CStack * target, const CSpell *source, bool persistent); void setStackColorFilter(const ColorFilter & effect, const CStack * target, const CSpell *source, bool persistent);
void addNewAnim(BattleAnimation *anim); //adds new anim to pendingAnims void addNewAnim(BattleAnimation *anim); //adds new anim to pendingAnims
void updateBattleAnimations();
const CStack* getActiveStack() const; const CStack* getActiveStack() const;
const CStack* getSelectedStack() const; const CStack* getSelectedStack() const;
void update();
/// returns position of animation needed to place stack in specific hex /// returns position of animation needed to place stack in specific hex
Point getStackPositionAtHex(BattleHex hexNum, const CStack * creature) const; Point getStackPositionAtHex(BattleHex hexNum, const CStack * creature) const;