diff --git a/client/battle/CBattleAnimations.cpp b/client/battle/CBattleAnimations.cpp index 5d179af1c..eeb03a94f 100644 --- a/client/battle/CBattleAnimations.cpp +++ b/client/battle/CBattleAnimations.cpp @@ -772,12 +772,12 @@ void CShootingAnimation::endAnim() delete this; } -CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx, int _dy, bool _Vflip) -:CBattleAnimation(_owner), effect(_effect), destTile(_destTile), customAnim(""), x(0), y(0), dx(_dx), dy(_dy), Vflip(_Vflip) +CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx, int _dy, bool _Vflip, bool _areaEffect) +:CBattleAnimation(_owner), effect(_effect), destTile(_destTile), customAnim(""), x(0), y(0), dx(_dx), dy(_dy), Vflip(_Vflip) , areaEffect(_areaEffect) {} -CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx, int _dy, bool _Vflip) -:CBattleAnimation(_owner), effect(-1), destTile(0), customAnim(_customAnim), x(_x), y(_y), dx(_dx), dy(_dy), Vflip(_Vflip) +CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx, int _dy, bool _Vflip, bool _areaEffect) +:CBattleAnimation(_owner), effect(-1), destTile(0), customAnim(_customAnim), x(_x), y(_y), dx(_dx), dy(_dy), Vflip(_Vflip), areaEffect(_areaEffect) {} bool CSpellEffectAnimation::init() @@ -821,6 +821,7 @@ bool CSpellEffectAnimation::init() be.maxFrame = be.anim->ourImages.size(); be.x = i * anim->width + owner->pos.x; be.y = j * anim->height + owner->pos.y; + be.position = BattleHex::INVALID; owner->battleEffects.push_back(be); } @@ -866,6 +867,7 @@ bool CSpellEffectAnimation::init() break; case 0: // Prayer and Lightning Bolt. case 1: + case 19: // Slow // Position effect with it's bottom center touching the bottom center of affected tile(s). be.x = tilePos.x + tilePos.w/2 - be.anim->width/2; be.y = tilePos.y + tilePos.h - be.anim->height; @@ -882,6 +884,12 @@ bool CSpellEffectAnimation::init() if (destStack != nullptr && destStack->doubleWide()) be.x += (destStack->attackerOwned ? -1 : 1)*tilePos.w/2; + //Indicate if effect should be drawn on top of everything or just on top of the hex + if(areaEffect) + be.position = BattleHex::INVALID; + else + be.position = destTile; + owner->battleEffects.push_back(be); } else //there is nothing to play diff --git a/client/battle/CBattleAnimations.h b/client/battle/CBattleAnimations.h index 10ffda68e..99d1ae5c2 100644 --- a/client/battle/CBattleAnimations.h +++ b/client/battle/CBattleAnimations.h @@ -217,12 +217,13 @@ private: std::string customAnim; int x, y, dx, dy; bool Vflip; + bool areaEffect; public: bool init(); void nextFrame(); void endAnim(); - CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false); - CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false); + CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _areaEffect = true); + CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _areaEffect = true); virtual ~CSpellEffectAnimation(){}; }; diff --git a/client/battle/CBattleInterface.cpp b/client/battle/CBattleInterface.cpp index 1b0411a7c..8de0ea75b 100644 --- a/client/battle/CBattleInterface.cpp +++ b/client/battle/CBattleInterface.cpp @@ -798,6 +798,18 @@ void CBattleInterface::show(SDL_Surface * to) } } + //Get all the spell effects that need to be drawn with the stack + std::vector battleEffectByHex[GameConstants::BFIELD_SIZE]; + std::vector topBattleEffects; + for (auto & battleEffect : battleEffects) + { + const BattleEffect *e = &battleEffect; + if(e->position.isValid()) + battleEffectByHex[e->position].push_back(e); + else + topBattleEffects.push_back(e); + } + for(auto & elem : stackDeadByHex) //showing dead stacks { for(size_t v=0; v flyingStacks; //flying stacks should be displayed later, over other stacks and obstacles if (!siegeH) { - for(int b = 0; b < GameConstants::BFIELD_SIZE; ++b) //showing alive stacks + for(int b = 0; b < GameConstants::BFIELD_SIZE; ++b) //showing alive stacks and spells { showObstacles(&hexToObstacle, obstacles, b, to); showAliveStacks(stackAliveByHex, b, &flyingStacks, to); + showBattleEffects(battleEffectByHex[b], to); } } // Siege drawing @@ -882,6 +895,7 @@ void CBattleInterface::show(SDL_Surface * to) int hex = j * 17 + k; showObstacles(&hexToObstacle, obstacles, hex, to); showAliveStacks(stackAliveByHex, hex, &flyingStacks, to); + showBattleEffects(battleEffectByHex[hex], to); showPieceOfWall(to, hex, stacks); } @@ -899,15 +913,7 @@ void CBattleInterface::show(SDL_Surface * to) projectileShowHelper(to); //showing spell effects - if(battleEffects.size()) - { - for(auto & elem : battleEffects) - { - SDL_Surface * bitmapToBlit = elem.anim->ourImages[(elem.frame)%elem.anim->ourImages.size()].bitmap; - SDL_Rect temp_rect = genRect(bitmapToBlit->h, bitmapToBlit->w, elem.x, elem.y); - SDL_BlitSurface(bitmapToBlit, nullptr, to, &temp_rect); - } - } + showBattleEffects(topBattleEffects, to); SDL_SetClipRect(to, &buf); //restoring previous clip_rect @@ -997,6 +1003,16 @@ void CBattleInterface::showObstacles(std::multimap *hexToObstacl } } +void CBattleInterface::showBattleEffects(const std::vector &battleEffects, SDL_Surface *to) +{ + for(auto & elem : battleEffects) + { + SDL_Surface * bitmapToBlit = elem->anim->ourImages[(elem->frame)%elem->anim->ourImages.size()].bitmap; + SDL_Rect temp_rect = genRect(bitmapToBlit->h, bitmapToBlit->w, elem->x, elem->y); + SDL_BlitSurface(bitmapToBlit, nullptr, to, &temp_rect); + } +} + void CBattleInterface::keyPressed(const SDL_KeyboardEvent & key) { if(key.keysym.sym == SDLK_q && key.state == SDL_PRESSED) @@ -1924,7 +1940,8 @@ void CBattleInterface::battleStacksEffectsSet(const SetStackEffect & sse) { for(auto & elem : sse.stacks) { - displayEffect(CGI->spellh->spells[effID]->mainEffectAnim, curInt->cb->battleGetStackByID(elem)->position); + bool areaEffect(CGI->spellh->spells[effID]->getTargetType() == CSpell::ETargetType::NO_TARGET); + displayEffect(CGI->spellh->spells[effID]->mainEffectAnim, curInt->cb->battleGetStackByID(elem)->position, areaEffect); } } else if (sse.stacks.size() == 1 && sse.effect.size() == 2) @@ -2015,9 +2032,9 @@ void CBattleInterface::castThisSpell(int spellID) } } -void CBattleInterface::displayEffect(ui32 effect, int destTile) +void CBattleInterface::displayEffect(ui32 effect, int destTile, bool areaEffect) { - addNewAnim(new CSpellEffectAnimation(this, effect, destTile)); + addNewAnim(new CSpellEffectAnimation(this, effect, destTile, 0, 0, false, areaEffect)); } void CBattleInterface::battleTriggerEffect(const BattleTriggerEffect & bte) diff --git a/client/battle/CBattleInterface.h b/client/battle/CBattleInterface.h index a1ca25ac8..de00609d0 100644 --- a/client/battle/CBattleInterface.h +++ b/client/battle/CBattleInterface.h @@ -70,6 +70,7 @@ struct BattleEffect int frame, maxFrame; CDefHandler * anim; //animation to display int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim + BattleHex position; //Indicates if effect which hex the effect is drawn on }; /// Small struct which is needed for drawing the parabolic trajectory of the catapult cannon @@ -158,6 +159,7 @@ private: void showAliveStacks(std::vector *aliveStacks, int hex, std::vector *flyingStacks, SDL_Surface *to); // loops through all stacks at a given hex position void showPieceOfWall(SDL_Surface * to, int hex, const std::vector & stacks); //helper function for show void showObstacles(std::multimap *hexToObstacle, std::vector > &obstacles, int hex, SDL_Surface *to); // show all obstacles at a given hex position + void showBattleEffects(const std::vector &battleEffects, SDL_Surface *to); //Show all spells in the given vector SDL_Surface *imageOfObstacle(const CObstacleInstance &oi) const; Point whereToBlitObstacleImage(SDL_Surface *image, const CObstacleInstance &obstacle) const; void redrawBackgroundWithHexes(const CStack * activeStack); @@ -263,7 +265,7 @@ public: void spellCast(const BattleSpellCast * sc); //called when a hero casts a spell void battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks void castThisSpell(int spellID); //called when player has chosen a spell from spellbook - void displayEffect(ui32 effect, int destTile); //displays effect of a spell on the battlefield; affected: true - attacker. false - defender + void displayEffect(ui32 effect, int destTile, bool areaEffect = true); //displays effect of a spell on the battlefield; affected: true - attacker. false - defender void battleTriggerEffect(const BattleTriggerEffect & bte); void setBattleCursor(const int myNumber); //really complex and messy, sets attackingHex void endAction(const BattleAction* action);