mirror of
https://github.com/vcmi/vcmi.git
synced 2025-09-16 09:26:28 +02:00
Removed delays due to thread waits from battle animations
This commit is contained in:
@@ -306,10 +306,8 @@ void MeleeAttackAnimation::nextFrame()
|
|||||||
size_t totalFrames = stackAnimation(attackingStack)->framesInGroup(getGroup());
|
size_t totalFrames = stackAnimation(attackingStack)->framesInGroup(getGroup());
|
||||||
|
|
||||||
if ( currentFrame * 2 >= totalFrames )
|
if ( currentFrame * 2 >= totalFrames )
|
||||||
{
|
owner.executeAnimationStage(EAnimationEvents::HIT);
|
||||||
if(owner.getAnimationCondition(EAnimationEvents::HIT) == false)
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::HIT, true);
|
|
||||||
}
|
|
||||||
AttackAnimation::nextFrame();
|
AttackAnimation::nextFrame();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -709,10 +707,8 @@ void RangedAttackAnimation::nextFrame()
|
|||||||
if (projectileEmitted)
|
if (projectileEmitted)
|
||||||
{
|
{
|
||||||
if (!owner.projectilesController->hasActiveProjectile(attackingStack, false))
|
if (!owner.projectilesController->hasActiveProjectile(attackingStack, false))
|
||||||
{
|
owner.executeAnimationStage(EAnimationEvents::HIT);
|
||||||
if(owner.getAnimationCondition(EAnimationEvents::HIT) == false)
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::HIT, true);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
AttackAnimation::nextFrame();
|
AttackAnimation::nextFrame();
|
||||||
@@ -1052,7 +1048,6 @@ bool HeroCastAnimation::init()
|
|||||||
hero->setPhase(EHeroAnimType::CAST_SPELL);
|
hero->setPhase(EHeroAnimType::CAST_SPELL);
|
||||||
|
|
||||||
hero->onPhaseFinished([&](){
|
hero->onPhaseFinished([&](){
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::HIT) == true);
|
|
||||||
delete this;
|
delete this;
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -1093,8 +1088,7 @@ void HeroCastAnimation::emitProjectile()
|
|||||||
|
|
||||||
void HeroCastAnimation::emitAnimationEvent()
|
void HeroCastAnimation::emitAnimationEvent()
|
||||||
{
|
{
|
||||||
if(owner.getAnimationCondition(EAnimationEvents::HIT) == false)
|
owner.executeAnimationStage(EAnimationEvents::HIT);
|
||||||
owner.setAnimationCondition(EAnimationEvents::HIT, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void HeroCastAnimation::nextFrame()
|
void HeroCastAnimation::nextFrame()
|
||||||
|
@@ -30,14 +30,22 @@ enum class EBattleEffect
|
|||||||
INVALID = -1,
|
INVALID = -1,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum class EAnimationEvents {
|
enum class EAnimationEvents
|
||||||
OPENING = 0, // battle opening sound is playing
|
{
|
||||||
ACTION = 1, // there are any ongoing animations
|
// any action
|
||||||
MOVEMENT = 2, // stacks are moving or turning around
|
ROTATE, // stacks rotate before action
|
||||||
BEFORE_HIT = 3, // effects played before all attack/defence/hit animations
|
|
||||||
ATTACK = 4, // attack and defence animations are playing
|
// movement action
|
||||||
HIT = 5, // hit & death animations are playing
|
MOVE_START, // stack starts movement
|
||||||
AFTER_HIT = 6, // after all hit & death animations are over
|
MOVEMENT, // movement animation loop starts
|
||||||
|
MOVE_END, // stack end movement
|
||||||
|
|
||||||
|
// attack/spellcast action
|
||||||
|
BEFORE_HIT, // attack and defence effects play, e.g. luck/death blow
|
||||||
|
ATTACK, // attack and defence animations are playing
|
||||||
|
HIT, // hit & death animations are playing
|
||||||
|
AFTER_HIT, // post-attack effect, e.g. phoenix rebirth
|
||||||
|
|
||||||
COUNT
|
COUNT
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -56,7 +56,7 @@ void BattleEffectsController::displayEffect(EBattleEffect effect, std::string so
|
|||||||
|
|
||||||
void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte)
|
void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte)
|
||||||
{
|
{
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
const CStack * stack = owner.curInt->cb->battleGetStackByID(bte.stackID);
|
const CStack * stack = owner.curInt->cb->battleGetStackByID(bte.stackID);
|
||||||
if(!stack)
|
if(!stack)
|
||||||
@@ -90,12 +90,12 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
|
|||||||
default:
|
default:
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
owner.waitForAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleEffectsController::startAction(const BattleAction* action)
|
void BattleEffectsController::startAction(const BattleAction* action)
|
||||||
{
|
{
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
const CStack *stack = owner.curInt->cb->battleGetStackByID(action->stackNumber);
|
const CStack *stack = owner.curInt->cb->battleGetStackByID(action->stackNumber);
|
||||||
|
|
||||||
@@ -110,7 +110,7 @@ void BattleEffectsController::startAction(const BattleAction* action)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
owner.waitForAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleEffectsController::collectRenderableObjects(BattleRenderer & renderer)
|
void BattleEffectsController::collectRenderableObjects(BattleRenderer & renderer)
|
||||||
|
@@ -56,9 +56,6 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
|
|||||||
, curInt(att)
|
, curInt(att)
|
||||||
, moveSoundHander(-1)
|
, moveSoundHander(-1)
|
||||||
{
|
{
|
||||||
for ( auto & event : animationEvents)
|
|
||||||
event.setn(false);
|
|
||||||
|
|
||||||
if(spectatorInt)
|
if(spectatorInt)
|
||||||
{
|
{
|
||||||
curInt = spectatorInt;
|
curInt = spectatorInt;
|
||||||
@@ -96,7 +93,7 @@ BattleInterface::BattleInterface(const CCreatureSet *army1, const CCreatureSet *
|
|||||||
obstacleController.reset(new BattleObstacleController(*this));
|
obstacleController.reset(new BattleObstacleController(*this));
|
||||||
|
|
||||||
adventureInt->onAudioPaused();
|
adventureInt->onAudioPaused();
|
||||||
setAnimationCondition(EAnimationEvents::OPENING, true);
|
ongoingAnimationsState.set(true);
|
||||||
|
|
||||||
GH.pushInt(windowObject);
|
GH.pushInt(windowObject);
|
||||||
windowObject->blockUI(true);
|
windowObject->blockUI(true);
|
||||||
@@ -131,7 +128,7 @@ void BattleInterface::playIntroSoundAndUnlockInterface()
|
|||||||
|
|
||||||
void BattleInterface::onIntroSoundPlayed()
|
void BattleInterface::onIntroSoundPlayed()
|
||||||
{
|
{
|
||||||
setAnimationCondition(EAnimationEvents::OPENING, false);
|
onAnimationsFinished();
|
||||||
CCS->musich->playMusicFromSet("battle", true, true);
|
CCS->musich->playMusicFromSet("battle", true, true);
|
||||||
if(tacticsMode)
|
if(tacticsMode)
|
||||||
tacticNextStack(nullptr);
|
tacticNextStack(nullptr);
|
||||||
@@ -147,10 +144,7 @@ BattleInterface::~BattleInterface()
|
|||||||
if (adventureInt)
|
if (adventureInt)
|
||||||
adventureInt->onAudioResumed();
|
adventureInt->onAudioResumed();
|
||||||
|
|
||||||
// may happen if user decided to close game while in battle
|
onAnimationsFinished();
|
||||||
if (getAnimationCondition(EAnimationEvents::ACTION) == true)
|
|
||||||
logGlobal->error("Shutting down BattleInterface during animation playback!");
|
|
||||||
setAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleInterface::redrawBattlefield()
|
void BattleInterface::redrawBattlefield()
|
||||||
@@ -217,7 +211,7 @@ void BattleInterface::stackAttacking( const StackAttackInfo & attackInfo )
|
|||||||
|
|
||||||
void BattleInterface::newRoundFirst( int round )
|
void BattleInterface::newRoundFirst( int round )
|
||||||
{
|
{
|
||||||
waitForAnimationCondition(EAnimationEvents::OPENING, false);
|
waitForAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleInterface::newRound(int number)
|
void BattleInterface::newRound(int number)
|
||||||
@@ -299,8 +293,7 @@ void BattleInterface::gateStateChanged(const EGateState state)
|
|||||||
|
|
||||||
void BattleInterface::battleFinished(const BattleResult& br)
|
void BattleInterface::battleFinished(const BattleResult& br)
|
||||||
{
|
{
|
||||||
assert(getAnimationCondition(EAnimationEvents::ACTION) == false);
|
checkForAnimations();
|
||||||
waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
stacksController->setActiveStack(nullptr);
|
stacksController->setActiveStack(nullptr);
|
||||||
|
|
||||||
CCS->curh->set(Cursor::Map::POINTER);
|
CCS->curh->set(Cursor::Map::POINTER);
|
||||||
@@ -337,7 +330,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
|||||||
EAnimationEvents::HIT:
|
EAnimationEvents::HIT:
|
||||||
EAnimationEvents::BEFORE_HIT;//FIXME: recheck whether this should be on projectile spawning
|
EAnimationEvents::BEFORE_HIT;//FIXME: recheck whether this should be on projectile spawning
|
||||||
|
|
||||||
executeOnAnimationCondition(group, true, [=]() {
|
addToAnimationStage(group, [=]() {
|
||||||
CCS->soundh->playSound(castSoundPath);
|
CCS->soundh->playSound(castSoundPath);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -348,7 +341,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
|||||||
|
|
||||||
if(casterStack != nullptr )
|
if(casterStack != nullptr )
|
||||||
{
|
{
|
||||||
executeOnAnimationCondition(EAnimationEvents::BEFORE_HIT, true, [=]()
|
addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]()
|
||||||
{
|
{
|
||||||
stacksController->addNewAnim(new CastAnimation(*this, casterStack, targetedTile, curInt->cb->battleGetStackByPos(targetedTile), spell));
|
stacksController->addNewAnim(new CastAnimation(*this, casterStack, targetedTile, curInt->cb->battleGetStackByPos(targetedTile), spell));
|
||||||
displaySpellCast(spell, casterStack->getPosition());
|
displaySpellCast(spell, casterStack->getPosition());
|
||||||
@@ -359,14 +352,14 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
|||||||
auto hero = sc->side ? defendingHero : attackingHero;
|
auto hero = sc->side ? defendingHero : attackingHero;
|
||||||
assert(hero);
|
assert(hero);
|
||||||
|
|
||||||
executeOnAnimationCondition(EAnimationEvents::BEFORE_HIT, true, [=]()
|
addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]()
|
||||||
{
|
{
|
||||||
stacksController->addNewAnim(new HeroCastAnimation(*this, hero, targetedTile, curInt->cb->battleGetStackByPos(targetedTile), spell));
|
stacksController->addNewAnim(new HeroCastAnimation(*this, hero, targetedTile, curInt->cb->battleGetStackByPos(targetedTile), spell));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||||
displaySpellHit(spell, targetedTile);
|
displaySpellHit(spell, targetedTile);
|
||||||
});
|
});
|
||||||
|
|
||||||
@@ -377,7 +370,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
|||||||
assert(stack);
|
assert(stack);
|
||||||
if(stack)
|
if(stack)
|
||||||
{
|
{
|
||||||
executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||||
displaySpellEffect(spell, stack->getPosition());
|
displaySpellEffect(spell, stack->getPosition());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -387,14 +380,14 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
|||||||
{
|
{
|
||||||
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
||||||
assert(stack);
|
assert(stack);
|
||||||
executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||||
effectsController->displayEffect(EBattleEffect::MAGIC_MIRROR, stack->getPosition());
|
effectsController->displayEffect(EBattleEffect::MAGIC_MIRROR, stack->getPosition());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!sc->resistedCres.empty())
|
if (!sc->resistedCres.empty())
|
||||||
{
|
{
|
||||||
executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||||
CCS->soundh->playSound("MAGICRES");
|
CCS->soundh->playSound("MAGICRES");
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -403,7 +396,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
|||||||
{
|
{
|
||||||
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
||||||
assert(stack);
|
assert(stack);
|
||||||
executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||||
effectsController->displayEffect(EBattleEffect::RESISTANCE, stack->getPosition());
|
effectsController->displayEffect(EBattleEffect::RESISTANCE, stack->getPosition());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -415,7 +408,7 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
|||||||
Point rightHero = Point(755, 30);
|
Point rightHero = Point(755, 30);
|
||||||
bool side = sc->side;
|
bool side = sc->side;
|
||||||
|
|
||||||
executeOnAnimationCondition(EAnimationEvents::AFTER_HIT, true, [=](){
|
addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){
|
||||||
stacksController->addNewAnim(new EffectAnimation(*this, side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero));
|
stacksController->addNewAnim(new EffectAnimation(*this, side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero));
|
||||||
stacksController->addNewAnim(new EffectAnimation(*this, side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero));
|
stacksController->addNewAnim(new EffectAnimation(*this, side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero));
|
||||||
});
|
});
|
||||||
@@ -611,8 +604,7 @@ void BattleInterface::tacticNextStack(const CStack * current)
|
|||||||
current = stacksController->getActiveStack();
|
current = stacksController->getActiveStack();
|
||||||
|
|
||||||
//no switching stacks when the current one is moving
|
//no switching stacks when the current one is moving
|
||||||
assert(getAnimationCondition(EAnimationEvents::ACTION) == false);
|
checkForAnimations();
|
||||||
waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
|
|
||||||
TStacks stacksOfMine = tacticianInterface->cb->battleGetStacks(CBattleCallback::ONLY_MINE);
|
TStacks stacksOfMine = tacticianInterface->cb->battleGetStacks(CBattleCallback::ONLY_MINE);
|
||||||
vstd::erase_if (stacksOfMine, &immobile);
|
vstd::erase_if (stacksOfMine, &immobile);
|
||||||
@@ -698,18 +690,24 @@ void BattleInterface::castThisSpell(SpellID spellID)
|
|||||||
actionsController->castThisSpell(spellID);
|
actionsController->castThisSpell(spellID);
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleInterface::setAnimationCondition( EAnimationEvents event, bool state)
|
void BattleInterface::executeStagedAnimations()
|
||||||
{
|
{
|
||||||
logAnim->debug("setAnimationCondition: %d -> %s", static_cast<int>(event), state ? "ON" : "OFF");
|
EAnimationEvents earliestStage = EAnimationEvents::COUNT;
|
||||||
|
|
||||||
size_t index = static_cast<size_t>(event);
|
for(const auto & event : awaitingEvents)
|
||||||
animationEvents[index].setn(state);
|
earliestStage = std::min(earliestStage, event.event);
|
||||||
|
|
||||||
|
if(earliestStage != EAnimationEvents::COUNT)
|
||||||
|
executeAnimationStage(earliestStage);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleInterface::executeAnimationStage(EAnimationEvents event)
|
||||||
|
{
|
||||||
decltype(awaitingEvents) executingEvents;
|
decltype(awaitingEvents) executingEvents;
|
||||||
|
|
||||||
for (auto it = awaitingEvents.begin(); it != awaitingEvents.end();)
|
for(auto it = awaitingEvents.begin(); it != awaitingEvents.end();)
|
||||||
{
|
{
|
||||||
if (it->event == event && it->eventState == state)
|
if(it->event == event)
|
||||||
{
|
{
|
||||||
executingEvents.push_back(*it);
|
executingEvents.push_back(*it);
|
||||||
it = awaitingEvents.erase(it);
|
it = awaitingEvents.erase(it);
|
||||||
@@ -717,27 +715,43 @@ void BattleInterface::setAnimationCondition( EAnimationEvents event, bool state)
|
|||||||
else
|
else
|
||||||
++it;
|
++it;
|
||||||
}
|
}
|
||||||
|
for(const auto & event : executingEvents)
|
||||||
for (auto const & event : executingEvents)
|
|
||||||
event.action();
|
event.action();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BattleInterface::getAnimationCondition( EAnimationEvents event)
|
void BattleInterface::onAnimationsStarted()
|
||||||
{
|
{
|
||||||
size_t index = static_cast<size_t>(event);
|
ongoingAnimationsState.setn(true);
|
||||||
return animationEvents[index].get();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleInterface::waitForAnimationCondition( EAnimationEvents event, bool state)
|
void BattleInterface::onAnimationsFinished()
|
||||||
|
{
|
||||||
|
ongoingAnimationsState.setn(false);
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleInterface::waitForAnimations()
|
||||||
{
|
{
|
||||||
auto unlockPim = vstd::makeUnlockGuard(*CPlayerInterface::pim);
|
auto unlockPim = vstd::makeUnlockGuard(*CPlayerInterface::pim);
|
||||||
size_t index = static_cast<size_t>(event);
|
ongoingAnimationsState.waitUntil(false);
|
||||||
animationEvents[index].waitUntil(state);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleInterface::executeOnAnimationCondition( EAnimationEvents event, bool state, const AwaitingAnimationAction & action)
|
bool BattleInterface::hasAnimations()
|
||||||
{
|
{
|
||||||
awaitingEvents.push_back({action, event, state});
|
return ongoingAnimationsState.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleInterface::checkForAnimations()
|
||||||
|
{
|
||||||
|
assert(!hasAnimations());
|
||||||
|
if(hasAnimations())
|
||||||
|
logGlobal->error("Unexpected animations state: expected all animations to be over, but some are still ongoing!");
|
||||||
|
|
||||||
|
waitForAnimations();
|
||||||
|
}
|
||||||
|
|
||||||
|
void BattleInterface::addToAnimationStage(EAnimationEvents event, const AwaitingAnimationAction & action)
|
||||||
|
{
|
||||||
|
awaitingEvents.push_back({action, event});
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleInterface::setBattleQueueVisibility(bool visible)
|
void BattleInterface::setBattleQueueVisibility(bool visible)
|
||||||
|
@@ -94,11 +94,10 @@ class BattleInterface
|
|||||||
struct AwaitingAnimationEvents {
|
struct AwaitingAnimationEvents {
|
||||||
AwaitingAnimationAction action;
|
AwaitingAnimationAction action;
|
||||||
EAnimationEvents event;
|
EAnimationEvents event;
|
||||||
bool eventState;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
/// Conditional variables that are set depending on ongoing animations on the battlefield
|
/// Conditional variables that are set depending on ongoing animations on the battlefield
|
||||||
std::array< CondSh<bool>, static_cast<size_t>(EAnimationEvents::COUNT)> animationEvents;
|
CondSh<bool> ongoingAnimationsState;
|
||||||
|
|
||||||
/// List of events that are waiting to be triggered
|
/// List of events that are waiting to be triggered
|
||||||
std::vector<AwaitingAnimationEvents> awaitingEvents;
|
std::vector<AwaitingAnimationEvents> awaitingEvents;
|
||||||
@@ -178,17 +177,14 @@ public:
|
|||||||
|
|
||||||
void setBattleQueueVisibility(bool visible);
|
void setBattleQueueVisibility(bool visible);
|
||||||
|
|
||||||
/// sets condition to targeted state and executes any awaiting actions
|
void executeStagedAnimations();
|
||||||
void setAnimationCondition( EAnimationEvents event, bool state);
|
void executeAnimationStage( EAnimationEvents event);
|
||||||
|
void onAnimationsStarted();
|
||||||
/// returns current state of condition
|
void onAnimationsFinished();
|
||||||
bool getAnimationCondition( EAnimationEvents event);
|
void waitForAnimations();
|
||||||
|
bool hasAnimations();
|
||||||
/// locks execution until selected condition reached targeted state
|
void checkForAnimations();
|
||||||
void waitForAnimationCondition( EAnimationEvents event, bool state);
|
void addToAnimationStage( EAnimationEvents event, const AwaitingAnimationAction & action);
|
||||||
|
|
||||||
/// adds action that will be executed one selected condition reached targeted state
|
|
||||||
void executeOnAnimationCondition( EAnimationEvents event, bool state, const AwaitingAnimationAction & action);
|
|
||||||
|
|
||||||
//call-ins
|
//call-ins
|
||||||
void startAction(const BattleAction* action);
|
void startAction(const BattleAction* action);
|
||||||
|
@@ -100,7 +100,7 @@ void BattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr<
|
|||||||
owner.stacksController->addNewAnim(new EffectAnimation(owner, spellObstacle->appearAnimation, whereTo, oi->pos));
|
owner.stacksController->addNewAnim(new EffectAnimation(owner, spellObstacle->appearAnimation, whereTo, oi->pos));
|
||||||
|
|
||||||
//so when multiple obstacles are added, they show up one after another
|
//so when multiple obstacles are added, they show up one after another
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
owner.waitForAnimations();
|
||||||
|
|
||||||
loadObstacleImage(*spellObstacle);
|
loadObstacleImage(*spellObstacle);
|
||||||
}
|
}
|
||||||
|
@@ -330,7 +330,7 @@ bool BattleSiegeController::isAttackableByCatapult(BattleHex hex) const
|
|||||||
|
|
||||||
void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
|
void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
|
||||||
{
|
{
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
if (ca.attacker != -1)
|
if (ca.attacker != -1)
|
||||||
{
|
{
|
||||||
@@ -352,8 +352,7 @@ void BattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
|
|||||||
owner.stacksController->addNewAnim(new EffectAnimation(owner, "SGEXPL.DEF", positions));
|
owner.stacksController->addNewAnim(new EffectAnimation(owner, "SGEXPL.DEF", positions));
|
||||||
}
|
}
|
||||||
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
owner.waitForAnimations();
|
||||||
owner.setAnimationCondition(EAnimationEvents::HIT, false);
|
|
||||||
|
|
||||||
for (auto attackInfo : ca.attackedParts)
|
for (auto attackInfo : ca.attackedParts)
|
||||||
{
|
{
|
||||||
|
@@ -160,7 +160,7 @@ void BattleStacksController::collectRenderableObjects(BattleRenderer & renderer)
|
|||||||
|
|
||||||
void BattleStacksController::stackReset(const CStack * stack)
|
void BattleStacksController::stackReset(const CStack * stack)
|
||||||
{
|
{
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
//reset orientation?
|
//reset orientation?
|
||||||
//stackFacingRight[stack->ID] = stack->side == BattleSide::ATTACKER;
|
//stackFacingRight[stack->ID] = stack->side == BattleSide::ATTACKER;
|
||||||
@@ -177,7 +177,7 @@ void BattleStacksController::stackReset(const CStack * stack)
|
|||||||
|
|
||||||
if(stack->alive() && animation->isDeadOrDying())
|
if(stack->alive() && animation->isDeadOrDying())
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::HIT, true, [=]()
|
owner.addToAnimationStage(EAnimationEvents::HIT, [=]()
|
||||||
{
|
{
|
||||||
addNewAnim(new ResurrectionAnimation(owner, stack));
|
addNewAnim(new ResurrectionAnimation(owner, stack));
|
||||||
});
|
});
|
||||||
@@ -221,7 +221,7 @@ void BattleStacksController::stackAdded(const CStack * stack, bool instant)
|
|||||||
auto shifterFade = ColorFilter::genAlphaShifter(0);
|
auto shifterFade = ColorFilter::genAlphaShifter(0);
|
||||||
setStackColorFilter(shifterFade, stack, nullptr, true);
|
setStackColorFilter(shifterFade, stack, nullptr, true);
|
||||||
|
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::HIT, true, [=]()
|
owner.addToAnimationStage(EAnimationEvents::HIT, [=]()
|
||||||
{
|
{
|
||||||
addNewAnim(new ColorTransformAnimation(owner, stack, "summonFadeIn", nullptr));
|
addNewAnim(new ColorTransformAnimation(owner, stack, "summonFadeIn", nullptr));
|
||||||
if (stack->isClone())
|
if (stack->isClone())
|
||||||
@@ -372,15 +372,19 @@ void BattleStacksController::updateBattleAnimations()
|
|||||||
vstd::erase(currentAnimations, nullptr);
|
vstd::erase(currentAnimations, nullptr);
|
||||||
|
|
||||||
if (hadAnimations && currentAnimations.empty())
|
if (hadAnimations && currentAnimations.empty())
|
||||||
owner.setAnimationCondition(EAnimationEvents::ACTION, false);
|
{
|
||||||
|
owner.executeStagedAnimations();
|
||||||
|
if (currentAnimations.empty())
|
||||||
|
owner.onAnimationsFinished();
|
||||||
|
}
|
||||||
|
|
||||||
initializeBattleAnimations();
|
initializeBattleAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleStacksController::addNewAnim(BattleAnimation *anim)
|
void BattleStacksController::addNewAnim(BattleAnimation *anim)
|
||||||
{
|
{
|
||||||
|
owner.onAnimationsStarted();
|
||||||
currentAnimations.push_back(anim);
|
currentAnimations.push_back(anim);
|
||||||
owner.setAnimationCondition(EAnimationEvents::ACTION, true);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleStacksController::stackRemoved(uint32_t stackID)
|
void BattleStacksController::stackRemoved(uint32_t stackID)
|
||||||
@@ -398,7 +402,7 @@ void BattleStacksController::stackRemoved(uint32_t stackID)
|
|||||||
|
|
||||||
void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos)
|
void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> attackedInfos)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
owner.addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||||
// remove any potentially erased petrification effect
|
// remove any potentially erased petrification effect
|
||||||
removeExpiredColorFilters();
|
removeExpiredColorFilters();
|
||||||
});
|
});
|
||||||
@@ -423,7 +427,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
|||||||
// if (needsReverse && !attackedInfo.defender->isFrozen())
|
// if (needsReverse && !attackedInfo.defender->isFrozen())
|
||||||
if (needsReverse && stackAnimation[attackedInfo.defender->ID]->getType() != ECreatureAnimType::FROZEN)
|
if (needsReverse && stackAnimation[attackedInfo.defender->ID]->getType() != ECreatureAnimType::FROZEN)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::MOVEMENT, true, [=]()
|
owner.addToAnimationStage(EAnimationEvents::MOVEMENT, [=]()
|
||||||
{
|
{
|
||||||
addNewAnim(new ReverseAnimation(owner, attackedInfo.defender, attackedInfo.defender->getPosition()));
|
addNewAnim(new ReverseAnimation(owner, attackedInfo.defender, attackedInfo.defender->getPosition()));
|
||||||
});
|
});
|
||||||
@@ -437,7 +441,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
|||||||
|
|
||||||
EAnimationEvents usedEvent = useDefenceAnim ? EAnimationEvents::ATTACK : EAnimationEvents::HIT;
|
EAnimationEvents usedEvent = useDefenceAnim ? EAnimationEvents::ATTACK : EAnimationEvents::HIT;
|
||||||
|
|
||||||
owner.executeOnAnimationCondition(usedEvent, true, [=]()
|
owner.addToAnimationStage(usedEvent, [=]()
|
||||||
{
|
{
|
||||||
if (useDeathAnim)
|
if (useDeathAnim)
|
||||||
addNewAnim(new DeathAnimation(owner, attackedInfo.defender, attackedInfo.indirectAttack));
|
addNewAnim(new DeathAnimation(owner, attackedInfo.defender, attackedInfo.indirectAttack));
|
||||||
@@ -465,7 +469,7 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
|||||||
{
|
{
|
||||||
if (attackedInfo.rebirth)
|
if (attackedInfo.rebirth)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::AFTER_HIT, true, [=](){
|
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){
|
||||||
owner.effectsController->displayEffect(EBattleEffect::RESURRECT, "RESURECT", attackedInfo.defender->getPosition());
|
owner.effectsController->displayEffect(EBattleEffect::RESURRECT, "RESURECT", attackedInfo.defender->getPosition());
|
||||||
addNewAnim(new ResurrectionAnimation(owner, attackedInfo.defender));
|
addNewAnim(new ResurrectionAnimation(owner, attackedInfo.defender));
|
||||||
});
|
});
|
||||||
@@ -473,25 +477,26 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
|||||||
|
|
||||||
if (attackedInfo.killed && attackedInfo.defender->summoned)
|
if (attackedInfo.killed && attackedInfo.defender->summoned)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::AFTER_HIT, true, [=](){
|
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){
|
||||||
addNewAnim(new ColorTransformAnimation(owner, attackedInfo.defender, "summonFadeOut", nullptr));
|
addNewAnim(new ColorTransformAnimation(owner, attackedInfo.defender, "summonFadeOut", nullptr));
|
||||||
stackRemoved(attackedInfo.defender->ID);
|
stackRemoved(attackedInfo.defender->ID);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
executeAttackAnimations();
|
owner.executeStagedAnimations();
|
||||||
|
owner.waitForAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleStacksController::stackTeleported(const CStack *stack, std::vector<BattleHex> destHex, int distance)
|
void BattleStacksController::stackTeleported(const CStack *stack, std::vector<BattleHex> destHex, int distance)
|
||||||
{
|
{
|
||||||
assert(destHex.size() > 0);
|
assert(destHex.size() > 0);
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
owner.addToAnimationStage(EAnimationEvents::HIT, [=](){
|
||||||
addNewAnim( new ColorTransformAnimation(owner, stack, "teleportFadeOut", nullptr) );
|
addNewAnim( new ColorTransformAnimation(owner, stack, "teleportFadeOut", nullptr) );
|
||||||
});
|
});
|
||||||
|
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::AFTER_HIT, true, [=](){
|
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=](){
|
||||||
stackAnimation[stack->ID]->pos.moveTo(getStackPositionAtHex(destHex.back(), stack));
|
stackAnimation[stack->ID]->pos.moveTo(getStackPositionAtHex(destHex.back(), stack));
|
||||||
addNewAnim( new ColorTransformAnimation(owner, stack, "teleportFadeIn", nullptr) );
|
addNewAnim( new ColorTransformAnimation(owner, stack, "teleportFadeIn", nullptr) );
|
||||||
});
|
});
|
||||||
@@ -502,42 +507,36 @@ void BattleStacksController::stackTeleported(const CStack *stack, std::vector<Ba
|
|||||||
void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance)
|
void BattleStacksController::stackMoved(const CStack *stack, std::vector<BattleHex> destHex, int distance)
|
||||||
{
|
{
|
||||||
assert(destHex.size() > 0);
|
assert(destHex.size() > 0);
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
bool stackTeleports = stack->hasBonus(Selector::typeSubtype(Bonus::FLYING, 1));
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::MOVEMENT, true);
|
|
||||||
|
|
||||||
auto enqueMoveEnd = [&](){
|
|
||||||
addNewAnim(new MovementEndAnimation(owner, stack, destHex.back()));
|
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, [&](){
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::MOVEMENT, false);
|
|
||||||
});
|
|
||||||
};
|
|
||||||
|
|
||||||
auto enqueMove = [&](){
|
|
||||||
if (!stackTeleports)
|
|
||||||
{
|
|
||||||
addNewAnim(new MovementAnimation(owner, stack, destHex, distance));
|
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, enqueMoveEnd);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
enqueMoveEnd();
|
|
||||||
};
|
|
||||||
|
|
||||||
auto enqueMoveStart = [&](){
|
|
||||||
addNewAnim(new MovementStartAnimation(owner, stack));
|
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, enqueMove);
|
|
||||||
};
|
|
||||||
|
|
||||||
if(shouldRotate(stack, stack->getPosition(), destHex[0]))
|
if(shouldRotate(stack, stack->getPosition(), destHex[0]))
|
||||||
{
|
{
|
||||||
addNewAnim(new ReverseAnimation(owner, stack, stack->getPosition()));
|
owner.addToAnimationStage(EAnimationEvents::ROTATE, [&]()
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::ACTION, false, enqueMoveStart);
|
{
|
||||||
|
addNewAnim(new ReverseAnimation(owner, stack, stack->getPosition()));
|
||||||
|
});
|
||||||
}
|
}
|
||||||
else
|
|
||||||
enqueMoveStart();
|
|
||||||
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::MOVEMENT, false);
|
owner.addToAnimationStage(EAnimationEvents::MOVE_START, [&]()
|
||||||
|
{
|
||||||
|
addNewAnim(new MovementStartAnimation(owner, stack));
|
||||||
|
});
|
||||||
|
|
||||||
|
if (!stack->hasBonus(Selector::typeSubtype(Bonus::FLYING, 1)))
|
||||||
|
{
|
||||||
|
owner.addToAnimationStage(EAnimationEvents::MOVEMENT, [&]()
|
||||||
|
{
|
||||||
|
addNewAnim(new MovementAnimation(owner, stack, destHex, distance));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
owner.addToAnimationStage(EAnimationEvents::MOVE_END, [&]()
|
||||||
|
{
|
||||||
|
addNewAnim(new MovementEndAnimation(owner, stack, destHex.back()));
|
||||||
|
});
|
||||||
|
|
||||||
|
owner.executeStagedAnimations();
|
||||||
|
owner.waitForAnimations();
|
||||||
}
|
}
|
||||||
|
|
||||||
bool BattleStacksController::shouldAttackFacingRight(const CStack * attacker, const CStack * defender)
|
bool BattleStacksController::shouldAttackFacingRight(const CStack * attacker, const CStack * defender)
|
||||||
@@ -554,7 +553,7 @@ bool BattleStacksController::shouldAttackFacingRight(const CStack * attacker, co
|
|||||||
|
|
||||||
void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
||||||
{
|
{
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
auto attacker = info.attacker;
|
auto attacker = info.attacker;
|
||||||
auto defender = info.defender;
|
auto defender = info.defender;
|
||||||
@@ -574,7 +573,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
|||||||
|
|
||||||
if (needsReverse)
|
if (needsReverse)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::MOVEMENT, true, [=]()
|
owner.addToAnimationStage(EAnimationEvents::MOVEMENT, [=]()
|
||||||
{
|
{
|
||||||
addNewAnim(new ReverseAnimation(owner, attacker, attacker->getPosition()));
|
addNewAnim(new ReverseAnimation(owner, attacker, attacker->getPosition()));
|
||||||
});
|
});
|
||||||
@@ -582,7 +581,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
|||||||
|
|
||||||
if(info.lucky)
|
if(info.lucky)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::BEFORE_HIT, true, [=]() {
|
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
|
||||||
owner.appendBattleLog(info.attacker->formatGeneralMessage(-45));
|
owner.appendBattleLog(info.attacker->formatGeneralMessage(-45));
|
||||||
owner.effectsController->displayEffect(EBattleEffect::GOOD_LUCK, "GOODLUCK", attacker->getPosition());
|
owner.effectsController->displayEffect(EBattleEffect::GOOD_LUCK, "GOODLUCK", attacker->getPosition());
|
||||||
});
|
});
|
||||||
@@ -590,7 +589,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
|||||||
|
|
||||||
if(info.unlucky)
|
if(info.unlucky)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::BEFORE_HIT, true, [=]() {
|
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
|
||||||
owner.appendBattleLog(info.attacker->formatGeneralMessage(-44));
|
owner.appendBattleLog(info.attacker->formatGeneralMessage(-44));
|
||||||
owner.effectsController->displayEffect(EBattleEffect::BAD_LUCK, "BADLUCK", attacker->getPosition());
|
owner.effectsController->displayEffect(EBattleEffect::BAD_LUCK, "BADLUCK", attacker->getPosition());
|
||||||
});
|
});
|
||||||
@@ -598,20 +597,20 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
|||||||
|
|
||||||
if(info.deathBlow)
|
if(info.deathBlow)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::BEFORE_HIT, true, [=]() {
|
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
|
||||||
owner.appendBattleLog(info.attacker->formatGeneralMessage(365));
|
owner.appendBattleLog(info.attacker->formatGeneralMessage(365));
|
||||||
owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, "DEATHBLO", defender->getPosition());
|
owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, "DEATHBLO", defender->getPosition());
|
||||||
});
|
});
|
||||||
|
|
||||||
for(auto elem : info.secondaryDefender)
|
for(auto elem : info.secondaryDefender)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::BEFORE_HIT, true, [=]() {
|
owner.addToAnimationStage(EAnimationEvents::BEFORE_HIT, [=]() {
|
||||||
owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, elem->getPosition());
|
owner.effectsController->displayEffect(EBattleEffect::DEATH_BLOW, elem->getPosition());
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::ATTACK, true, [=]()
|
owner.addToAnimationStage(EAnimationEvents::ATTACK, [=]()
|
||||||
{
|
{
|
||||||
if (info.indirectAttack)
|
if (info.indirectAttack)
|
||||||
{
|
{
|
||||||
@@ -625,7 +624,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
|||||||
|
|
||||||
if (info.spellEffect != SpellID::NONE)
|
if (info.spellEffect != SpellID::NONE)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::HIT, true, [=]()
|
owner.addToAnimationStage(EAnimationEvents::HIT, [=]()
|
||||||
{
|
{
|
||||||
owner.displaySpellHit(spellEffect.toSpell(), tile);
|
owner.displaySpellHit(spellEffect.toSpell(), tile);
|
||||||
});
|
});
|
||||||
@@ -633,7 +632,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
|||||||
|
|
||||||
if (info.lifeDrain)
|
if (info.lifeDrain)
|
||||||
{
|
{
|
||||||
owner.executeOnAnimationCondition(EAnimationEvents::AFTER_HIT, true, [=]()
|
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=]()
|
||||||
{
|
{
|
||||||
owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, "DRAINLIF", attacker->getPosition());
|
owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, "DRAINLIF", attacker->getPosition());
|
||||||
});
|
});
|
||||||
@@ -642,32 +641,6 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
|
|||||||
//return, animation playback will be handled by stacksAreAttacked
|
//return, animation playback will be handled by stacksAreAttacked
|
||||||
}
|
}
|
||||||
|
|
||||||
void BattleStacksController::executeAttackAnimations()
|
|
||||||
{
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::MOVEMENT, true);
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::MOVEMENT, false);
|
|
||||||
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::BEFORE_HIT, true);
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::BEFORE_HIT, false);
|
|
||||||
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::ATTACK, true);
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::ATTACK, false);
|
|
||||||
|
|
||||||
// Note that HIT event can also be emitted by attack animation
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::HIT, true);
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::HIT, false);
|
|
||||||
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::AFTER_HIT, true);
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
owner.setAnimationCondition(EAnimationEvents::AFTER_HIT, false);
|
|
||||||
|
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
|
||||||
}
|
|
||||||
|
|
||||||
bool BattleStacksController::shouldRotate(const CStack * stack, const BattleHex & oldPos, const BattleHex & nextHex) const
|
bool BattleStacksController::shouldRotate(const CStack * stack, const BattleHex & oldPos, const BattleHex & nextHex) const
|
||||||
{
|
{
|
||||||
Point begPosition = getStackPositionAtHex(oldPos,stack);
|
Point begPosition = getStackPositionAtHex(oldPos,stack);
|
||||||
@@ -683,7 +656,7 @@ bool BattleStacksController::shouldRotate(const CStack * stack, const BattleHex
|
|||||||
|
|
||||||
void BattleStacksController::endAction(const BattleAction* action)
|
void BattleStacksController::endAction(const BattleAction* action)
|
||||||
{
|
{
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
owner.checkForAnimations();
|
||||||
|
|
||||||
//check if we should reverse stacks
|
//check if we should reverse stacks
|
||||||
TStacks stacks = owner.curInt->cb->battleGetStacks(CBattleCallback::MINE_AND_ENEMY);
|
TStacks stacks = owner.curInt->cb->battleGetStacks(CBattleCallback::MINE_AND_ENEMY);
|
||||||
@@ -697,14 +670,8 @@ void BattleStacksController::endAction(const BattleAction* action)
|
|||||||
addNewAnim(new ReverseAnimation(owner, s, s->getPosition()));
|
addNewAnim(new ReverseAnimation(owner, s, s->getPosition()));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
owner.executeStagedAnimations();
|
||||||
|
owner.waitForAnimations();
|
||||||
//Ensure that all animation flags were reset
|
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::OPENING) == false);
|
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::MOVEMENT) == false);
|
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::ATTACK) == false);
|
|
||||||
assert(owner.getAnimationCondition(EAnimationEvents::HIT) == false);
|
|
||||||
|
|
||||||
owner.windowObject->blockUI(activeStack == nullptr);
|
owner.windowObject->blockUI(activeStack == nullptr);
|
||||||
removeExpiredColorFilters();
|
removeExpiredColorFilters();
|
||||||
@@ -718,7 +685,8 @@ void BattleStacksController::startAction(const BattleAction* action)
|
|||||||
void BattleStacksController::stackActivated(const CStack *stack)
|
void BattleStacksController::stackActivated(const CStack *stack)
|
||||||
{
|
{
|
||||||
stackToActivate = stack;
|
stackToActivate = stack;
|
||||||
owner.waitForAnimationCondition(EAnimationEvents::ACTION, false);
|
owner.waitForAnimations();
|
||||||
|
logAnim->debug("Activating next stack");
|
||||||
owner.activateStack();
|
owner.activateStack();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -850,7 +818,6 @@ void BattleStacksController::updateHoveredStacks()
|
|||||||
stackAnimation[stack->ID]->setBorderColor(AnimationControls::getBlueBorder());
|
stackAnimation[stack->ID]->setBorderColor(AnimationControls::getBlueBorder());
|
||||||
if (stackAnimation[stack->ID]->framesInGroup(ECreatureAnimType::MOUSEON) > 0 && stack->alive() && !stack->isFrozen())
|
if (stackAnimation[stack->ID]->framesInGroup(ECreatureAnimType::MOUSEON) > 0 && stack->alive() && !stack->isFrozen())
|
||||||
stackAnimation[stack->ID]->playOnce(ECreatureAnimType::MOUSEON);
|
stackAnimation[stack->ID]->playOnce(ECreatureAnimType::MOUSEON);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mouseHoveredStacks = newStacks;
|
mouseHoveredStacks = newStacks;
|
||||||
@@ -862,7 +829,7 @@ std::vector<const CStack *> BattleStacksController::selectHoveredStacks()
|
|||||||
if (!activeStack)
|
if (!activeStack)
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
if(owner.getAnimationCondition(EAnimationEvents::ACTION) == true)
|
if(owner.hasAnimations())
|
||||||
return {};
|
return {};
|
||||||
|
|
||||||
auto hoveredQueueUnitId = owner.windowObject->getQueueHoveredUnitId();
|
auto hoveredQueueUnitId = owner.windowObject->getQueueHoveredUnitId();
|
||||||
|
@@ -88,7 +88,6 @@ class BattleStacksController
|
|||||||
|
|
||||||
std::shared_ptr<IImage> getStackAmountBox(const CStack * stack);
|
std::shared_ptr<IImage> getStackAmountBox(const CStack * stack);
|
||||||
|
|
||||||
void executeAttackAnimations();
|
|
||||||
void removeExpiredColorFilters();
|
void removeExpiredColorFilters();
|
||||||
|
|
||||||
void initializeBattleAnimations();
|
void initializeBattleAnimations();
|
||||||
|
@@ -179,6 +179,12 @@ void BattleWindow::deactivate()
|
|||||||
|
|
||||||
void BattleWindow::keyPressed(const SDL_Keycode & key)
|
void BattleWindow::keyPressed(const SDL_Keycode & key)
|
||||||
{
|
{
|
||||||
|
if(owner.battleIntroSoundChannel != -1)
|
||||||
|
{
|
||||||
|
CCS->soundh->stopSound(owner.battleIntroSoundChannel);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
if(key == SDLK_q)
|
if(key == SDLK_q)
|
||||||
{
|
{
|
||||||
toggleQueueVisibility();
|
toggleQueueVisibility();
|
||||||
@@ -189,10 +195,7 @@ void BattleWindow::keyPressed(const SDL_Keycode & key)
|
|||||||
}
|
}
|
||||||
else if(key == SDLK_ESCAPE)
|
else if(key == SDLK_ESCAPE)
|
||||||
{
|
{
|
||||||
if(owner.getAnimationCondition(EAnimationEvents::OPENING) == true)
|
owner.actionsController->endCastingSpell();
|
||||||
CCS->soundh->stopSound(owner.battleIntroSoundChannel);
|
|
||||||
else
|
|
||||||
owner.actionsController->endCastingSpell();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user