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)
ourStack = shere->owner == owner.curInt->playerID;
//stack may have changed, update selection border
owner.stacksController->setHoveredStack(shere);
localActions.clear();
illegalActions.clear();

View File

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

View File

@@ -13,6 +13,7 @@
#include "BattleSiegeController.h"
#include "BattleInterfaceClasses.h"
#include "BattleInterface.h"
#include "BattleActionsController.h"
#include "BattleAnimationClasses.h"
#include "BattleFieldController.h"
#include "BattleEffectsController.h"
@@ -27,6 +28,7 @@
#include "../gui/CAnimation.h"
#include "../gui/CGuiHandler.h"
#include "../gui/Canvas.h"
#include "../../lib/spells/ISpellMechanics.h"
#include "../../CCallback.h"
#include "../../lib/battle/BattleHex.h"
@@ -69,7 +71,6 @@ static void onAnimationFinished(const CStack *stack, std::weak_ptr<CreatureAnima
BattleStacksController::BattleStacksController(BattleInterface & owner):
owner(owner),
activeStack(nullptr),
mouseHoveredStack(nullptr),
stackToActivate(nullptr),
selectedStack(nullptr),
stackCanCastSpell(false),
@@ -242,30 +243,6 @@ void BattleStacksController::setActiveStack(const CStack *stack)
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
{
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
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())
return false;
@@ -377,6 +351,12 @@ void BattleStacksController::showStack(Canvas & canvas, const CStack * stack)
stackAnimation[stack->ID]->incrementFrame(float(GH.mainFPSmng->getElapsedMilliseconds()) / 1000);
}
void BattleStacksController::update()
{
updateHoveredStacks();
updateBattleAnimations();
}
void BattleStacksController::updateBattleAnimations()
{
for (auto & elem : currentAnimations)
@@ -390,7 +370,6 @@ void BattleStacksController::updateBattleAnimations()
elem->tryInitialize();
}
bool hadAnimations = !currentAnimations.empty();
vstd::erase(currentAnimations, nullptr);
@@ -674,7 +653,6 @@ void BattleStacksController::endAction(const BattleAction* action)
void BattleStacksController::startAction(const BattleAction* action)
{
setHoveredStack(nullptr);
removeExpiredColorFilters();
}
@@ -819,3 +797,77 @@ void BattleStacksController::removeExpiredColorFilters()
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
const CStack *activeStack;
/// stack below mouse pointer, used for border animation
const CStack *mouseHoveredStack;
/// stacks below mouse pointer (multiple stacks possible while spellcasting), used for border animation
std::vector<const CStack *> mouseHoveredStacks;
///when animation is playing, we should wait till the end to make the next stack active; nullptr of none
const CStack *stackToActivate;
@@ -94,6 +94,12 @@ class BattleStacksController
void executeAttackAnimations();
void removeExpiredColorFilters();
void updateBattleAnimations();
void updateHoveredStacks();
std::vector<const CStack *> selectHoveredStacks();
public:
BattleStacksController(BattleInterface & owner);
@@ -117,7 +123,6 @@ public:
void activateStack(); //sets activeStack to stackToActivate etc. //FIXME: No, it's not clear at all
void setActiveStack(const CStack *stack);
void setHoveredStack(const CStack *stack);
void setSelectedStack(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
void setStackColorFilter(const ColorFilter & effect, const CStack * target, const CSpell *source, bool persistent);
void addNewAnim(BattleAnimation *anim); //adds new anim to pendingAnims
void updateBattleAnimations();
const CStack* getActiveStack() const;
const CStack* getSelectedStack() const;
void update();
/// returns position of animation needed to place stack in specific hex
Point getStackPositionAtHex(BattleHex hexNum, const CStack * creature) const;