mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
moved battle obstacle handling into separate class
This commit is contained in:
parent
a65dd0726d
commit
9c2a6dc9fc
@ -14,6 +14,7 @@
|
|||||||
#include "CBattleInterfaceClasses.h"
|
#include "CBattleInterfaceClasses.h"
|
||||||
#include "CCreatureAnimation.h"
|
#include "CCreatureAnimation.h"
|
||||||
#include "CBattleProjectileController.h"
|
#include "CBattleProjectileController.h"
|
||||||
|
#include "CBattleObstacleController.h"
|
||||||
#include "CBattleSiegeController.h"
|
#include "CBattleSiegeController.h"
|
||||||
|
|
||||||
#include "../CBitmapHandler.h"
|
#include "../CBitmapHandler.h"
|
||||||
@ -335,48 +336,7 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
|||||||
|
|
||||||
backgroundWithHexes = CSDL_Ext::newSurface(background->w, background->h, screen);
|
backgroundWithHexes = CSDL_Ext::newSurface(background->w, background->h, screen);
|
||||||
|
|
||||||
//preparing obstacle defs
|
obstacleController.reset(new CBattleObstacleController(this));
|
||||||
auto obst = curInt->cb->battleGetAllObstacles();
|
|
||||||
for(auto & elem : obst)
|
|
||||||
{
|
|
||||||
if(elem->obstacleType == CObstacleInstance::USUAL)
|
|
||||||
{
|
|
||||||
std::string animationName = elem->getInfo().animation;
|
|
||||||
|
|
||||||
auto cached = animationsCache.find(animationName);
|
|
||||||
|
|
||||||
if(cached == animationsCache.end())
|
|
||||||
{
|
|
||||||
auto animation = std::make_shared<CAnimation>(animationName);
|
|
||||||
animationsCache[animationName] = animation;
|
|
||||||
obstacleAnimations[elem->uniqueID] = animation;
|
|
||||||
animation->preload();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
obstacleAnimations[elem->uniqueID] = cached->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else if (elem->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
|
||||||
{
|
|
||||||
std::string animationName = elem->getInfo().animation;
|
|
||||||
|
|
||||||
auto cached = animationsCache.find(animationName);
|
|
||||||
|
|
||||||
if(cached == animationsCache.end())
|
|
||||||
{
|
|
||||||
auto animation = std::make_shared<CAnimation>();
|
|
||||||
animation->setCustom(animationName, 0, 0);
|
|
||||||
animationsCache[animationName] = animation;
|
|
||||||
obstacleAnimations[elem->uniqueID] = animation;
|
|
||||||
animation->preload();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
obstacleAnimations[elem->uniqueID] = cached->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for(auto hex : bfield)
|
for(auto hex : bfield)
|
||||||
addChild(hex.get());
|
addChild(hex.get());
|
||||||
@ -2625,45 +2585,7 @@ Rect CBattleInterface::hexPosition(BattleHex hex) const
|
|||||||
|
|
||||||
void CBattleInterface::obstaclePlaced(const CObstacleInstance & oi)
|
void CBattleInterface::obstaclePlaced(const CObstacleInstance & oi)
|
||||||
{
|
{
|
||||||
//so when multiple obstacles are added, they show up one after another
|
obstacleController->obstaclePlaced(oi);
|
||||||
waitForAnims();
|
|
||||||
|
|
||||||
//soundBase::soundID sound; // FIXME(v.markovtsev): soundh->playSound() is commented in the end => warning
|
|
||||||
|
|
||||||
std::string defname;
|
|
||||||
|
|
||||||
switch(oi.obstacleType)
|
|
||||||
{
|
|
||||||
case CObstacleInstance::SPELL_CREATED:
|
|
||||||
{
|
|
||||||
auto &spellObstacle = dynamic_cast<const SpellCreatedObstacle&>(oi);
|
|
||||||
defname = spellObstacle.appearAnimation;
|
|
||||||
//TODO: sound
|
|
||||||
//soundBase::QUIKSAND
|
|
||||||
//soundBase::LANDMINE
|
|
||||||
//soundBase::FORCEFLD
|
|
||||||
//soundBase::fireWall
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
logGlobal->error("I don't know how to animate appearing obstacle of type %d", (int)oi.obstacleType);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
auto animation = std::make_shared<CAnimation>(defname);
|
|
||||||
animation->preload();
|
|
||||||
|
|
||||||
auto first = animation->getImage(0, 0);
|
|
||||||
if(!first)
|
|
||||||
return;
|
|
||||||
|
|
||||||
//we assume here that effect graphics have the same size as the usual obstacle image
|
|
||||||
// -> if we know how to blit obstacle, let's blit the effect in the same place
|
|
||||||
Point whereTo = getObstaclePosition(first, oi);
|
|
||||||
addNewAnim(new CEffectAnimation(this, animation, whereTo.x, whereTo.y));
|
|
||||||
|
|
||||||
//TODO we need to wait after playing sound till it's finished, otherwise it overlaps and sounds really bad
|
|
||||||
//CCS->soundh->playSound(sound);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const CGHeroInstance *CBattleInterface::currentHero() const
|
const CGHeroInstance *CBattleInterface::currentHero() const
|
||||||
@ -2772,7 +2694,9 @@ void CBattleInterface::showBackground(SDL_Surface *to)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
showBackgroundImage(to);
|
showBackgroundImage(to);
|
||||||
showAbsoluteObstacles(to);
|
obstacleController->showAbsoluteObstacles(to);
|
||||||
|
if ( siegeController )
|
||||||
|
siegeController->showAbsoluteObstacles(to);
|
||||||
}
|
}
|
||||||
showHighlightedHexes(to);
|
showHighlightedHexes(to);
|
||||||
}
|
}
|
||||||
@ -2786,22 +2710,6 @@ void CBattleInterface::showBackgroundImage(SDL_Surface *to)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::showAbsoluteObstacles(SDL_Surface * to)
|
|
||||||
{
|
|
||||||
//Blit absolute obstacles
|
|
||||||
for(auto & oi : curInt->cb->battleGetAllObstacles())
|
|
||||||
{
|
|
||||||
if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
|
||||||
{
|
|
||||||
auto img = getObstacleImage(*oi);
|
|
||||||
if(img)
|
|
||||||
img->draw(to, pos.x + oi->getInfo().width, pos.y + oi->getInfo().height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if ( siegeController )
|
|
||||||
siegeController->showAbsoluteObstacles(to);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBattleInterface::showHighlightedHexes(SDL_Surface *to)
|
void CBattleInterface::showHighlightedHexes(SDL_Surface *to)
|
||||||
{
|
{
|
||||||
@ -2902,7 +2810,7 @@ void CBattleInterface::showBattlefieldObjects(SDL_Surface *to)
|
|||||||
{
|
{
|
||||||
if (siegeController)
|
if (siegeController)
|
||||||
siegeController->showPiecesOfWall(to, hex.walls);
|
siegeController->showPiecesOfWall(to, hex.walls);
|
||||||
showObstacles(to, hex.obstacles);
|
obstacleController->showObstacles(to, hex.obstacles);
|
||||||
showAliveStacks(to, hex.alive);
|
showAliveStacks(to, hex.alive);
|
||||||
showBattleEffects(to, hex.effects);
|
showBattleEffects(to, hex.effects);
|
||||||
};
|
};
|
||||||
@ -3039,19 +2947,6 @@ void CBattleInterface::showStacks(SDL_Surface *to, std::vector<const CStack *> s
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::showObstacles(SDL_Surface * to, std::vector<std::shared_ptr<const CObstacleInstance>> & obstacles)
|
|
||||||
{
|
|
||||||
for(auto & obstacle : obstacles)
|
|
||||||
{
|
|
||||||
auto img = getObstacleImage(*obstacle);
|
|
||||||
if(img)
|
|
||||||
{
|
|
||||||
Point p = getObstaclePosition(img, *obstacle);
|
|
||||||
img->draw(to, p.x, p.y);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBattleInterface::showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects)
|
void CBattleInterface::showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects)
|
||||||
{
|
{
|
||||||
for (auto & elem : battleEffects)
|
for (auto & elem : battleEffects)
|
||||||
@ -3180,19 +3075,8 @@ BattleObjectsByHex CBattleInterface::sortObjectsByHex()
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Sort obstacles
|
// Sort obstacles
|
||||||
{
|
obstacleController->sortObjectsByHex(sorted);
|
||||||
std::map<BattleHex, std::shared_ptr<const CObstacleInstance>> backgroundObstacles;
|
|
||||||
for (auto &obstacle : curInt->cb->battleGetAllObstacles()) {
|
|
||||||
if (obstacle->obstacleType != CObstacleInstance::ABSOLUTE_OBSTACLE
|
|
||||||
&& obstacle->obstacleType != CObstacleInstance::MOAT) {
|
|
||||||
backgroundObstacles[obstacle->pos] = obstacle;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for (auto &op : backgroundObstacles)
|
|
||||||
{
|
|
||||||
sorted.beforeAll.obstacles.push_back(op.second);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// Sort wall parts
|
// Sort wall parts
|
||||||
if (siegeController)
|
if (siegeController)
|
||||||
siegeController->sortObjectsByHex(sorted);
|
siegeController->sortObjectsByHex(sorted);
|
||||||
@ -3237,58 +3121,6 @@ void CBattleInterface::updateBattleAnimations()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<IImage> CBattleInterface::getObstacleImage(const CObstacleInstance & oi)
|
|
||||||
{
|
|
||||||
int frameIndex = (animCount+1) *25 / getAnimSpeed();
|
|
||||||
std::shared_ptr<CAnimation> animation;
|
|
||||||
|
|
||||||
if(oi.obstacleType == CObstacleInstance::USUAL || oi.obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
|
||||||
{
|
|
||||||
animation = obstacleAnimations[oi.uniqueID];
|
|
||||||
}
|
|
||||||
else if(oi.obstacleType == CObstacleInstance::SPELL_CREATED)
|
|
||||||
{
|
|
||||||
const SpellCreatedObstacle * spellObstacle = dynamic_cast<const SpellCreatedObstacle *>(&oi);
|
|
||||||
if(!spellObstacle)
|
|
||||||
return std::shared_ptr<IImage>();
|
|
||||||
|
|
||||||
std::string animationName = spellObstacle->animation;
|
|
||||||
|
|
||||||
auto cacheIter = animationsCache.find(animationName);
|
|
||||||
|
|
||||||
if(cacheIter == animationsCache.end())
|
|
||||||
{
|
|
||||||
logAnim->trace("Creating obstacle animation %s", animationName);
|
|
||||||
|
|
||||||
animation = std::make_shared<CAnimation>(animationName);
|
|
||||||
animation->preload();
|
|
||||||
animationsCache[animationName] = animation;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
animation = cacheIter->second;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if(animation)
|
|
||||||
{
|
|
||||||
frameIndex %= animation->size(0);
|
|
||||||
return animation->getImage(frameIndex, 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return nullptr;
|
|
||||||
}
|
|
||||||
|
|
||||||
Point CBattleInterface::getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle)
|
|
||||||
{
|
|
||||||
int offset = obstacle.getAnimationYOffset(image->height());
|
|
||||||
|
|
||||||
Rect r = hexPosition(obstacle.pos);
|
|
||||||
r.y += 42 - image->height() + offset;
|
|
||||||
|
|
||||||
return r.topLeft();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CBattleInterface::redrawBackgroundWithHexes(const CStack *activeStack)
|
void CBattleInterface::redrawBackgroundWithHexes(const CStack *activeStack)
|
||||||
{
|
{
|
||||||
attackableHexes.clear();
|
attackableHexes.clear();
|
||||||
@ -3308,16 +3140,7 @@ void CBattleInterface::redrawBackgroundWithHexes(const CStack *activeStack)
|
|||||||
//prepare background graphic with hexes and shaded hexes
|
//prepare background graphic with hexes and shaded hexes
|
||||||
blitAt(background, 0, 0, backgroundWithHexes);
|
blitAt(background, 0, 0, backgroundWithHexes);
|
||||||
|
|
||||||
//draw absolute obstacles (cliffs and so on)
|
obstacleController->redrawBackgroundWithHexes();
|
||||||
for(auto & oi : curInt->cb->battleGetAllObstacles())
|
|
||||||
{
|
|
||||||
if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
|
||||||
{
|
|
||||||
auto img = getObstacleImage(*oi);
|
|
||||||
if(img)
|
|
||||||
img->draw(backgroundWithHexes, oi->getInfo().width, oi->getInfo().height);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings["battle"]["stackRange"].Bool())
|
if (settings["battle"]["stackRange"].Bool())
|
||||||
{
|
{
|
||||||
|
@ -60,6 +60,7 @@ class IImage;
|
|||||||
|
|
||||||
class CBattleProjectileController;
|
class CBattleProjectileController;
|
||||||
class CBattleSiegeController;
|
class CBattleSiegeController;
|
||||||
|
class CBattleObstacleController;
|
||||||
|
|
||||||
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
/// Small struct which contains information about the id of the attacked stack, the damage dealt,...
|
||||||
struct StackAttackedInfo
|
struct StackAttackedInfo
|
||||||
@ -139,9 +140,6 @@ private:
|
|||||||
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
||||||
std::map<int32_t, std::shared_ptr<CCreatureAnimation>> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
std::map<int32_t, std::shared_ptr<CCreatureAnimation>> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||||
|
|
||||||
std::map<std::string, std::shared_ptr<CAnimation>> animationsCache;
|
|
||||||
std::map<si32, std::shared_ptr<CAnimation>> obstacleAnimations;
|
|
||||||
|
|
||||||
std::map<int, bool> creDir; // <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
|
std::map<int, bool> creDir; // <creatureID, if false reverse creature's animation> //TODO: move it to battle callback
|
||||||
ui8 animCount;
|
ui8 animCount;
|
||||||
const CStack *activeStack; //number of active stack; nullptr - no one
|
const CStack *activeStack; //number of active stack; nullptr - no one
|
||||||
@ -200,7 +198,6 @@ private:
|
|||||||
void showBackground(SDL_Surface *to);
|
void showBackground(SDL_Surface *to);
|
||||||
|
|
||||||
void showBackgroundImage(SDL_Surface *to);
|
void showBackgroundImage(SDL_Surface *to);
|
||||||
void showAbsoluteObstacles(SDL_Surface *to);
|
|
||||||
void showHighlightedHexes(SDL_Surface *to);
|
void showHighlightedHexes(SDL_Surface *to);
|
||||||
void showHighlightedHex(SDL_Surface *to, BattleHex hex, bool darkBorder = false);
|
void showHighlightedHex(SDL_Surface *to, BattleHex hex, bool darkBorder = false);
|
||||||
void showInterface(SDL_Surface *to);
|
void showInterface(SDL_Surface *to);
|
||||||
@ -209,17 +206,12 @@ private:
|
|||||||
|
|
||||||
void showAliveStacks(SDL_Surface *to, std::vector<const CStack *> stacks);
|
void showAliveStacks(SDL_Surface *to, std::vector<const CStack *> stacks);
|
||||||
void showStacks(SDL_Surface *to, std::vector<const CStack *> stacks);
|
void showStacks(SDL_Surface *to, std::vector<const CStack *> stacks);
|
||||||
void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance>> &obstacles);
|
|
||||||
|
|
||||||
void showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects);
|
void showBattleEffects(SDL_Surface *to, const std::vector<const BattleEffect *> &battleEffects);
|
||||||
|
|
||||||
BattleObjectsByHex sortObjectsByHex();
|
BattleObjectsByHex sortObjectsByHex();
|
||||||
void updateBattleAnimations();
|
void updateBattleAnimations();
|
||||||
|
|
||||||
std::shared_ptr<IImage> getObstacleImage(const CObstacleInstance & oi);
|
|
||||||
|
|
||||||
Point getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle);
|
|
||||||
|
|
||||||
void redrawBackgroundWithHexes(const CStack *activeStack);
|
void redrawBackgroundWithHexes(const CStack *activeStack);
|
||||||
/** End of battle screen blitting methods */
|
/** End of battle screen blitting methods */
|
||||||
|
|
||||||
@ -227,6 +219,7 @@ private:
|
|||||||
public:
|
public:
|
||||||
std::unique_ptr<CBattleProjectileController> projectilesController;
|
std::unique_ptr<CBattleProjectileController> projectilesController;
|
||||||
std::unique_ptr<CBattleSiegeController> siegeController;
|
std::unique_ptr<CBattleSiegeController> siegeController;
|
||||||
|
std::unique_ptr<CBattleObstacleController> obstacleController;
|
||||||
|
|
||||||
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
static CondSh<bool> animsAreDisplayed; //for waiting with the end of battle for end of anims
|
||||||
static CondSh<BattleAction *> givenCommand; //data != nullptr if we have i.e. moved current unit
|
static CondSh<BattleAction *> givenCommand; //data != nullptr if we have i.e. moved current unit
|
||||||
@ -356,4 +349,5 @@ public:
|
|||||||
friend class CClickableHex;
|
friend class CClickableHex;
|
||||||
friend class CBattleProjectileController;
|
friend class CBattleProjectileController;
|
||||||
friend class CBattleSiegeController;
|
friend class CBattleSiegeController;
|
||||||
|
friend class CBattleObstacleController;
|
||||||
};
|
};
|
||||||
|
@ -9,4 +9,207 @@
|
|||||||
*/
|
*/
|
||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CBattleObstacleController.h"
|
#include "CBattleObstacleController.h"
|
||||||
|
#include "CBattleInterface.h"
|
||||||
|
#include "../CPlayerInterface.h"
|
||||||
|
#include "../../CCallback.h"
|
||||||
|
#include "../../lib/battle/CObstacleInstance.h"
|
||||||
|
#include "../../lib/ObstacleHandler.h"
|
||||||
|
#include "../gui/CAnimation.h"
|
||||||
|
|
||||||
|
CBattleObstacleController::CBattleObstacleController(CBattleInterface * owner):
|
||||||
|
owner(owner)
|
||||||
|
{
|
||||||
|
auto obst = owner->curInt->cb->battleGetAllObstacles();
|
||||||
|
for(auto & elem : obst)
|
||||||
|
{
|
||||||
|
if(elem->obstacleType == CObstacleInstance::USUAL)
|
||||||
|
{
|
||||||
|
std::string animationName = elem->getInfo().animation;
|
||||||
|
|
||||||
|
auto cached = animationsCache.find(animationName);
|
||||||
|
|
||||||
|
if(cached == animationsCache.end())
|
||||||
|
{
|
||||||
|
auto animation = std::make_shared<CAnimation>(animationName);
|
||||||
|
animationsCache[animationName] = animation;
|
||||||
|
obstacleAnimations[elem->uniqueID] = animation;
|
||||||
|
animation->preload();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obstacleAnimations[elem->uniqueID] = cached->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else if (elem->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
||||||
|
{
|
||||||
|
std::string animationName = elem->getInfo().animation;
|
||||||
|
|
||||||
|
auto cached = animationsCache.find(animationName);
|
||||||
|
|
||||||
|
if(cached == animationsCache.end())
|
||||||
|
{
|
||||||
|
auto animation = std::make_shared<CAnimation>();
|
||||||
|
animation->setCustom(animationName, 0, 0);
|
||||||
|
animationsCache[animationName] = animation;
|
||||||
|
obstacleAnimations[elem->uniqueID] = animation;
|
||||||
|
animation->preload();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
obstacleAnimations[elem->uniqueID] = cached->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBattleObstacleController::obstaclePlaced(const CObstacleInstance & oi)
|
||||||
|
{
|
||||||
|
//so when multiple obstacles are added, they show up one after another
|
||||||
|
owner->waitForAnims();
|
||||||
|
|
||||||
|
//soundBase::soundID sound; // FIXME(v.markovtsev): soundh->playSound() is commented in the end => warning
|
||||||
|
|
||||||
|
std::string defname;
|
||||||
|
|
||||||
|
switch(oi.obstacleType)
|
||||||
|
{
|
||||||
|
case CObstacleInstance::SPELL_CREATED:
|
||||||
|
{
|
||||||
|
auto &spellObstacle = dynamic_cast<const SpellCreatedObstacle&>(oi);
|
||||||
|
defname = spellObstacle.appearAnimation;
|
||||||
|
//TODO: sound
|
||||||
|
//soundBase::QUIKSAND
|
||||||
|
//soundBase::LANDMINE
|
||||||
|
//soundBase::FORCEFLD
|
||||||
|
//soundBase::fireWall
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
logGlobal->error("I don't know how to animate appearing obstacle of type %d", (int)oi.obstacleType);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
auto animation = std::make_shared<CAnimation>(defname);
|
||||||
|
animation->preload();
|
||||||
|
|
||||||
|
auto first = animation->getImage(0, 0);
|
||||||
|
if(!first)
|
||||||
|
return;
|
||||||
|
|
||||||
|
//we assume here that effect graphics have the same size as the usual obstacle image
|
||||||
|
// -> if we know how to blit obstacle, let's blit the effect in the same place
|
||||||
|
Point whereTo = getObstaclePosition(first, oi);
|
||||||
|
owner->addNewAnim(new CEffectAnimation(owner, animation, whereTo.x, whereTo.y));
|
||||||
|
|
||||||
|
//TODO we need to wait after playing sound till it's finished, otherwise it overlaps and sounds really bad
|
||||||
|
//CCS->soundh->playSound(sound);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBattleObstacleController::showAbsoluteObstacles(SDL_Surface * to)
|
||||||
|
{
|
||||||
|
//Blit absolute obstacles
|
||||||
|
for(auto & oi : owner->curInt->cb->battleGetAllObstacles())
|
||||||
|
{
|
||||||
|
if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
||||||
|
{
|
||||||
|
auto img = getObstacleImage(*oi);
|
||||||
|
if(img)
|
||||||
|
img->draw(to, owner->pos.x + oi->getInfo().width, owner->pos.y + oi->getInfo().height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBattleObstacleController::showObstacles(SDL_Surface * to, std::vector<std::shared_ptr<const CObstacleInstance>> & obstacles)
|
||||||
|
{
|
||||||
|
for(auto & obstacle : obstacles)
|
||||||
|
{
|
||||||
|
auto img = getObstacleImage(*obstacle);
|
||||||
|
if(img)
|
||||||
|
{
|
||||||
|
Point p = getObstaclePosition(img, *obstacle);
|
||||||
|
img->draw(to, p.x, p.y);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBattleObstacleController::sortObjectsByHex(BattleObjectsByHex & sorted)
|
||||||
|
{
|
||||||
|
std::map<BattleHex, std::shared_ptr<const CObstacleInstance>> backgroundObstacles;
|
||||||
|
for (auto &obstacle : owner->curInt->cb->battleGetAllObstacles()) {
|
||||||
|
if (obstacle->obstacleType != CObstacleInstance::ABSOLUTE_OBSTACLE
|
||||||
|
&& obstacle->obstacleType != CObstacleInstance::MOAT) {
|
||||||
|
backgroundObstacles[obstacle->pos] = obstacle;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for (auto &op : backgroundObstacles)
|
||||||
|
{
|
||||||
|
sorted.beforeAll.obstacles.push_back(op.second);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
std::shared_ptr<IImage> CBattleObstacleController::getObstacleImage(const CObstacleInstance & oi)
|
||||||
|
{
|
||||||
|
int frameIndex = (owner->animCount+1) *25 / owner->getAnimSpeed();
|
||||||
|
std::shared_ptr<CAnimation> animation;
|
||||||
|
|
||||||
|
if(oi.obstacleType == CObstacleInstance::USUAL || oi.obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
||||||
|
{
|
||||||
|
animation = obstacleAnimations[oi.uniqueID];
|
||||||
|
}
|
||||||
|
else if(oi.obstacleType == CObstacleInstance::SPELL_CREATED)
|
||||||
|
{
|
||||||
|
const SpellCreatedObstacle * spellObstacle = dynamic_cast<const SpellCreatedObstacle *>(&oi);
|
||||||
|
if(!spellObstacle)
|
||||||
|
return std::shared_ptr<IImage>();
|
||||||
|
|
||||||
|
std::string animationName = spellObstacle->animation;
|
||||||
|
|
||||||
|
auto cacheIter = animationsCache.find(animationName);
|
||||||
|
|
||||||
|
if(cacheIter == animationsCache.end())
|
||||||
|
{
|
||||||
|
logAnim->trace("Creating obstacle animation %s", animationName);
|
||||||
|
|
||||||
|
animation = std::make_shared<CAnimation>(animationName);
|
||||||
|
animation->preload();
|
||||||
|
animationsCache[animationName] = animation;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
animation = cacheIter->second;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if(animation)
|
||||||
|
{
|
||||||
|
frameIndex %= animation->size(0);
|
||||||
|
return animation->getImage(frameIndex, 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
|
||||||
|
Point CBattleObstacleController::getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle)
|
||||||
|
{
|
||||||
|
int offset = obstacle.getAnimationYOffset(image->height());
|
||||||
|
|
||||||
|
Rect r = owner->hexPosition(obstacle.pos);
|
||||||
|
r.y += 42 - image->height() + offset;
|
||||||
|
|
||||||
|
return r.topLeft();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CBattleObstacleController::redrawBackgroundWithHexes()
|
||||||
|
{
|
||||||
|
//draw absolute obstacles (cliffs and so on)
|
||||||
|
for(auto & oi : owner->curInt->cb->battleGetAllObstacles())
|
||||||
|
{
|
||||||
|
if(oi->obstacleType == CObstacleInstance::ABSOLUTE_OBSTACLE)
|
||||||
|
{
|
||||||
|
auto img = getObstacleImage(*oi);
|
||||||
|
if(img)
|
||||||
|
img->draw(owner->backgroundWithHexes, oi->getInfo().width, oi->getInfo().height);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
@ -9,7 +9,33 @@
|
|||||||
*/
|
*/
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
|
struct SDL_Surface;
|
||||||
|
struct BattleObjectsByHex;
|
||||||
|
class IImage;
|
||||||
|
class CAnimation;
|
||||||
|
class CBattleInterface;
|
||||||
|
class CObstacleInstance;
|
||||||
|
struct Point;
|
||||||
|
|
||||||
class CBattleObstacleController
|
class CBattleObstacleController
|
||||||
{
|
{
|
||||||
|
std::map<std::string, std::shared_ptr<CAnimation>> animationsCache;
|
||||||
|
|
||||||
|
CBattleInterface * owner;
|
||||||
|
|
||||||
|
std::map<si32, std::shared_ptr<CAnimation>> obstacleAnimations;
|
||||||
|
public:
|
||||||
|
CBattleObstacleController(CBattleInterface * owner);
|
||||||
|
|
||||||
|
void obstaclePlaced(const CObstacleInstance & oi);
|
||||||
|
void showObstacles(SDL_Surface *to, std::vector<std::shared_ptr<const CObstacleInstance>> &obstacles);
|
||||||
|
void showAbsoluteObstacles(SDL_Surface *to);
|
||||||
|
|
||||||
|
void sortObjectsByHex(BattleObjectsByHex & sorted);
|
||||||
|
|
||||||
|
std::shared_ptr<IImage> getObstacleImage(const CObstacleInstance & oi);
|
||||||
|
|
||||||
|
Point getObstaclePosition(std::shared_ptr<IImage> image, const CObstacleInstance & obstacle);
|
||||||
|
|
||||||
|
void redrawBackgroundWithHexes();
|
||||||
};
|
};
|
||||||
|
@ -145,7 +145,9 @@ void CBattleSiegeController::printPartOfWall(SDL_Surface *to, int what)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
CBattleSiegeController::CBattleSiegeController(CBattleInterface * owner, const CGTownInstance *siegeTown)
|
CBattleSiegeController::CBattleSiegeController(CBattleInterface * owner, const CGTownInstance *siegeTown):
|
||||||
|
owner(owner),
|
||||||
|
town(siegeTown)
|
||||||
{
|
{
|
||||||
owner->background = BitmapHandler::loadBitmap( getSiegeName(0), false );
|
owner->background = BitmapHandler::loadBitmap( getSiegeName(0), false );
|
||||||
ui8 siegeLevel = owner->curInt->cb->battleGetSiegeLevel();
|
ui8 siegeLevel = owner->curInt->cb->battleGetSiegeLevel();
|
||||||
|
Loading…
x
Reference in New Issue
Block a user