mirror of
https://github.com/vcmi/vcmi.git
synced 2025-08-13 19:54:17 +02:00
@@ -29,12 +29,9 @@ static long long pow(long long a, int b)
|
|||||||
|
|
||||||
CDefHandler::CDefHandler()
|
CDefHandler::CDefHandler()
|
||||||
{
|
{
|
||||||
notFreeImgs = false;
|
|
||||||
}
|
}
|
||||||
CDefHandler::~CDefHandler()
|
CDefHandler::~CDefHandler()
|
||||||
{
|
{
|
||||||
if (notFreeImgs)
|
|
||||||
return;
|
|
||||||
for (auto & elem : ourImages)
|
for (auto & elem : ourImages)
|
||||||
{
|
{
|
||||||
if (elem.bitmap)
|
if (elem.bitmap)
|
||||||
@@ -44,11 +41,6 @@ CDefHandler::~CDefHandler()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
CDefEssential::~CDefEssential()
|
|
||||||
{
|
|
||||||
for(auto & elem : ourImages)
|
|
||||||
SDL_FreeSurface(elem.bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CDefHandler::openFromMemory(ui8 *table, const std::string & name)
|
void CDefHandler::openFromMemory(ui8 *table, const std::string & name)
|
||||||
{
|
{
|
||||||
@@ -350,14 +342,6 @@ SDL_Surface * CDefHandler::getSprite (int SIndex, const ui8 * FDef, const SDL_Co
|
|||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
CDefEssential * CDefHandler::essentialize()
|
|
||||||
{
|
|
||||||
auto ret = new CDefEssential();
|
|
||||||
ret->ourImages = ourImages;
|
|
||||||
notFreeImgs = true;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
CDefHandler * CDefHandler::giveDef(const std::string & defName)
|
CDefHandler * CDefHandler::giveDef(const std::string & defName)
|
||||||
{
|
{
|
||||||
ResourceID resID(std::string("SPRITES/") + defName, EResType::ANIMATION);
|
ResourceID resID(std::string("SPRITES/") + defName, EResType::ANIMATION);
|
||||||
@@ -369,12 +353,4 @@ CDefHandler * CDefHandler::giveDef(const std::string & defName)
|
|||||||
nh->openFromMemory(data.get(), defName);
|
nh->openFromMemory(data.get(), defName);
|
||||||
return nh;
|
return nh;
|
||||||
}
|
}
|
||||||
CDefEssential * CDefHandler::giveDefEss(const std::string & defName)
|
|
||||||
{
|
|
||||||
CDefEssential * ret;
|
|
||||||
CDefHandler * temp = giveDef(defName);
|
|
||||||
ret = temp->essentialize();
|
|
||||||
delete temp;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
@@ -66,12 +66,6 @@ struct SSpriteDef
|
|||||||
ui32 TopMargin;
|
ui32 TopMargin;
|
||||||
} PACKED_STRUCT;
|
} PACKED_STRUCT;
|
||||||
|
|
||||||
class CDefEssential //DefHandler with images only
|
|
||||||
{
|
|
||||||
public:
|
|
||||||
std::vector<Cimage> ourImages;
|
|
||||||
~CDefEssential();
|
|
||||||
};
|
|
||||||
|
|
||||||
class CDefHandler
|
class CDefHandler
|
||||||
{
|
{
|
||||||
@@ -84,20 +78,17 @@ private:
|
|||||||
int group;
|
int group;
|
||||||
} ;
|
} ;
|
||||||
std::vector<SEntry> SEntries ;
|
std::vector<SEntry> SEntries ;
|
||||||
|
|
||||||
void openFromMemory(ui8 * table, const std::string & name);
|
void openFromMemory(ui8 * table, const std::string & name);
|
||||||
SDL_Surface * getSprite (int SIndex, const ui8 * FDef, const SDL_Color * palette) const;
|
SDL_Surface * getSprite (int SIndex, const ui8 * FDef, const SDL_Color * palette) const;
|
||||||
public:
|
public:
|
||||||
int width, height; //width and height
|
int width, height; //width and height
|
||||||
std::string defName;
|
std::string defName;
|
||||||
std::vector<Cimage> ourImages;
|
std::vector<Cimage> ourImages;
|
||||||
bool notFreeImgs;
|
|
||||||
|
|
||||||
CDefHandler();
|
CDefHandler();
|
||||||
~CDefHandler();
|
~CDefHandler();
|
||||||
|
|
||||||
CDefEssential * essentialize();
|
|
||||||
|
|
||||||
static CDefHandler * giveDef(const std::string & defName);
|
static CDefHandler * giveDef(const std::string & defName);
|
||||||
static CDefEssential * giveDefEss(const std::string & defName);
|
|
||||||
};
|
};
|
||||||
|
@@ -232,16 +232,10 @@ std::shared_ptr<CAnimation> Graphics::loadHeroFlagAnimation(const std::string &
|
|||||||
|
|
||||||
for(const auto & rotation : rotations)
|
for(const auto & rotation : rotations)
|
||||||
{
|
{
|
||||||
const int sourceGroup = rotation.first;
|
const int sourceGroup = rotation.first;
|
||||||
const int targetGroup = rotation.second;
|
const int targetGroup = rotation.second;
|
||||||
|
|
||||||
for(size_t frame = 0; frame < anim->size(sourceGroup); ++frame)
|
anim->createFlippedGroup(sourceGroup, targetGroup);
|
||||||
{
|
|
||||||
anim->duplicateImage(sourceGroup, frame, targetGroup);
|
|
||||||
|
|
||||||
IImage * image = anim->getImage(frame, targetGroup);
|
|
||||||
image->verticalFlip();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return anim;
|
return anim;
|
||||||
@@ -262,15 +256,10 @@ std::shared_ptr<CAnimation> Graphics::loadHeroAnimation(const std::string &name)
|
|||||||
|
|
||||||
for(const auto & rotation : rotations)
|
for(const auto & rotation : rotations)
|
||||||
{
|
{
|
||||||
const int sourceGroup = rotation.first;
|
const int sourceGroup = rotation.first;
|
||||||
const int targetGroup = rotation.second;
|
const int targetGroup = rotation.second;
|
||||||
|
|
||||||
for(size_t frame = 0; frame < anim->size(sourceGroup); ++frame)
|
anim->createFlippedGroup(sourceGroup, targetGroup);
|
||||||
{
|
|
||||||
anim->duplicateImage(sourceGroup, frame, targetGroup);
|
|
||||||
IImage * image = anim->getImage(frame, targetGroup);
|
|
||||||
image->verticalFlip();
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return anim;
|
return anim;
|
||||||
|
@@ -16,11 +16,11 @@
|
|||||||
#include "CBattleInterface.h"
|
#include "CBattleInterface.h"
|
||||||
#include "CCreatureAnimation.h"
|
#include "CCreatureAnimation.h"
|
||||||
|
|
||||||
#include "../CDefHandler.h"
|
|
||||||
#include "../CGameInfo.h"
|
#include "../CGameInfo.h"
|
||||||
#include "../CMusicHandler.h"
|
#include "../CMusicHandler.h"
|
||||||
#include "../CPlayerInterface.h"
|
#include "../CPlayerInterface.h"
|
||||||
#include "../Graphics.h"
|
#include "../Graphics.h"
|
||||||
|
#include "../gui/CAnimation.h"
|
||||||
#include "../gui/CCursorHandler.h"
|
#include "../gui/CCursorHandler.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/SDL_Extensions.h"
|
#include "../gui/SDL_Extensions.h"
|
||||||
@@ -58,13 +58,13 @@ bool CBattleAnimation::isEarliest(bool perStackConcurrency)
|
|||||||
{
|
{
|
||||||
int lowestMoveID = owner->animIDhelper + 5;
|
int lowestMoveID = owner->animIDhelper + 5;
|
||||||
CBattleStackAnimation * thAnim = dynamic_cast<CBattleStackAnimation *>(this);
|
CBattleStackAnimation * thAnim = dynamic_cast<CBattleStackAnimation *>(this);
|
||||||
CSpellEffectAnimation * thSen = dynamic_cast<CSpellEffectAnimation *>(this);
|
CEffectAnimation * thSen = dynamic_cast<CEffectAnimation *>(this);
|
||||||
|
|
||||||
for(auto & elem : owner->pendingAnims)
|
for(auto & elem : owner->pendingAnims)
|
||||||
{
|
{
|
||||||
|
|
||||||
CBattleStackAnimation * stAnim = dynamic_cast<CBattleStackAnimation *>(elem.first);
|
CBattleStackAnimation * stAnim = dynamic_cast<CBattleStackAnimation *>(elem.first);
|
||||||
CSpellEffectAnimation * sen = dynamic_cast<CSpellEffectAnimation *>(elem.first);
|
CEffectAnimation * sen = dynamic_cast<CEffectAnimation *>(elem.first);
|
||||||
if(perStackConcurrency && stAnim && thAnim && stAnim->stack->ID != thAnim->stack->ID)
|
if(perStackConcurrency && stAnim && thAnim && stAnim->stack->ID != thAnim->stack->ID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -171,7 +171,7 @@ bool CDefenceAnimation::init()
|
|||||||
if(attAnim && attAnim->stack->ID != stack->ID)
|
if(attAnim && attAnim->stack->ID != stack->ID)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
CSpellEffectAnimation * sen = dynamic_cast<CSpellEffectAnimation *>(elem.first);
|
CEffectAnimation * sen = dynamic_cast<CEffectAnimation *>(elem.first);
|
||||||
if (sen)
|
if (sen)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
@@ -243,7 +243,7 @@ CCreatureAnim::EAnimType CDefenceAnimation::getMyAnimType()
|
|||||||
if(killed)
|
if(killed)
|
||||||
return CCreatureAnim::DEATH;
|
return CCreatureAnim::DEATH;
|
||||||
|
|
||||||
if (vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
if(vstd::contains(stack->state, EBattleStackState::DEFENDING_ANIM))
|
||||||
return CCreatureAnim::DEFENCE;
|
return CCreatureAnim::DEFENCE;
|
||||||
|
|
||||||
return CCreatureAnim::HITTED;
|
return CCreatureAnim::HITTED;
|
||||||
@@ -270,10 +270,15 @@ void CDefenceAnimation::nextFrame()
|
|||||||
|
|
||||||
void CDefenceAnimation::endAnim()
|
void CDefenceAnimation::endAnim()
|
||||||
{
|
{
|
||||||
if (killed)
|
if(killed)
|
||||||
|
{
|
||||||
myAnim->setType(CCreatureAnim::DEAD);
|
myAnim->setType(CCreatureAnim::DEAD);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
myAnim->setType(CCreatureAnim::HOLDING);
|
myAnim->setType(CCreatureAnim::HOLDING);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
CBattleAnimation::endAnim();
|
CBattleAnimation::endAnim();
|
||||||
|
|
||||||
@@ -785,13 +790,13 @@ bool CShootingAnimation::init()
|
|||||||
spi.dx = animSpeed;
|
spi.dx = animSpeed;
|
||||||
spi.dy = 0;
|
spi.dy = 0;
|
||||||
|
|
||||||
SDL_Surface * img = owner->idToProjectile[spi.creID]->ourImages[0].bitmap;
|
IImage * img = owner->idToProjectile[spi.creID]->getImage(0);
|
||||||
|
|
||||||
// Add explosion anim
|
// Add explosion anim
|
||||||
Point animPos(destPos.x - 126 + img->w / 2,
|
Point animPos(destPos.x - 126 + img->width() / 2,
|
||||||
destPos.y - 105 + img->h / 2);
|
destPos.y - 105 + img->height() / 2);
|
||||||
|
|
||||||
owner->addNewAnim( new CSpellEffectAnimation(owner, catapultDamage ? "SGEXPL.DEF" : "CSGRCK.DEF", animPos.x, animPos.y));
|
owner->addNewAnim( new CEffectAnimation(owner, catapultDamage ? "SGEXPL.DEF" : "CSGRCK.DEF", animPos.x, animPos.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
auto & angles = shooterInfo->animation.missleFrameAngles;
|
auto & angles = shooterInfo->animation.missleFrameAngles;
|
||||||
@@ -801,7 +806,7 @@ bool CShootingAnimation::init()
|
|||||||
owner->initStackProjectile(shooter);
|
owner->initStackProjectile(shooter);
|
||||||
|
|
||||||
// only frames below maxFrame are usable: anything higher is either no present or we don't know when it should be used
|
// only frames below maxFrame are usable: anything higher is either no present or we don't know when it should be used
|
||||||
size_t maxFrame = std::min<size_t>(angles.size(), owner->idToProjectile.at(spi.creID)->ourImages.size());
|
size_t maxFrame = std::min<size_t>(angles.size(), owner->idToProjectile.at(spi.creID)->size(0));
|
||||||
|
|
||||||
assert(maxFrame > 0);
|
assert(maxFrame > 0);
|
||||||
|
|
||||||
@@ -872,35 +877,40 @@ void CShootingAnimation::endAnim()
|
|||||||
delete this;
|
delete this;
|
||||||
}
|
}
|
||||||
|
|
||||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx, int _dy, bool _Vflip, bool _alignToBottom)
|
CEffectAnimation::CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx, int _dy, bool _Vflip, bool _alignToBottom)
|
||||||
:CBattleAnimation(_owner), effect(_effect), destTile(_destTile), customAnim(""), x(-1), y(-1), dx(_dx), dy(_dy), Vflip(_Vflip), alignToBottom(_alignToBottom)
|
: CBattleAnimation(_owner),
|
||||||
|
destTile(BattleHex::INVALID),
|
||||||
|
customAnim(_customAnim),
|
||||||
|
x(_x),
|
||||||
|
y(_y),
|
||||||
|
dx(_dx),
|
||||||
|
dy(_dy),
|
||||||
|
Vflip(_Vflip),
|
||||||
|
alignToBottom(_alignToBottom)
|
||||||
{
|
{
|
||||||
logAnim->debug("Created spell anim for effect #%d", effect);
|
logAnim->debug("Created effect animation %s", customAnim);
|
||||||
}
|
}
|
||||||
|
|
||||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx, int _dy, bool _Vflip, bool _alignToBottom)
|
CEffectAnimation::CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip, bool _alignToBottom)
|
||||||
:CBattleAnimation(_owner), effect(-1), destTile(BattleHex::INVALID), customAnim(_customAnim), x(_x), y(_y), dx(_dx), dy(_dy), Vflip(_Vflip), alignToBottom(_alignToBottom)
|
: CBattleAnimation(_owner),
|
||||||
|
destTile(_destTile),
|
||||||
|
customAnim(_customAnim),
|
||||||
|
x(-1),
|
||||||
|
y(-1),
|
||||||
|
dx(0),
|
||||||
|
dy(0),
|
||||||
|
Vflip(_Vflip),
|
||||||
|
alignToBottom(_alignToBottom)
|
||||||
{
|
{
|
||||||
logAnim->debug("Created spell anim for %s", customAnim);
|
logAnim->debug("Created effect animation %s", customAnim);
|
||||||
}
|
|
||||||
|
|
||||||
CSpellEffectAnimation::CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip, bool _alignToBottom)
|
|
||||||
:CBattleAnimation(_owner), effect(-1), destTile(_destTile), customAnim(_customAnim), x(-1), y(-1), dx(0), dy(0), Vflip(_Vflip), alignToBottom(_alignToBottom)
|
|
||||||
{
|
|
||||||
logAnim->debug("Created spell anim for %s", customAnim);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
bool CSpellEffectAnimation::init()
|
bool CEffectAnimation::init()
|
||||||
{
|
{
|
||||||
if(!isEarliest(true))
|
if(!isEarliest(true))
|
||||||
return false;
|
return false;
|
||||||
|
|
||||||
if(customAnim.empty() && effect != ui32(-1) && !graphics->battleACToDef[effect].empty())
|
|
||||||
{
|
|
||||||
customAnim = graphics->battleACToDef[effect][0];
|
|
||||||
}
|
|
||||||
|
|
||||||
if(customAnim.empty())
|
if(customAnim.empty())
|
||||||
{
|
{
|
||||||
endAnim();
|
endAnim();
|
||||||
@@ -909,97 +919,88 @@ bool CSpellEffectAnimation::init()
|
|||||||
|
|
||||||
const bool areaEffect = (!destTile.isValid() && x == -1 && y == -1);
|
const bool areaEffect = (!destTile.isValid() && x == -1 && y == -1);
|
||||||
|
|
||||||
|
std::shared_ptr<CAnimation> animation = std::make_shared<CAnimation>(customAnim);
|
||||||
|
|
||||||
|
animation->preload();
|
||||||
|
if(Vflip)
|
||||||
|
animation->verticalFlip();
|
||||||
|
|
||||||
|
IImage * first = animation->getImage(0, 0, true);
|
||||||
|
if(!first)
|
||||||
|
{
|
||||||
|
endAnim();
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
if(areaEffect) //f.e. armageddon
|
if(areaEffect) //f.e. armageddon
|
||||||
{
|
{
|
||||||
CDefHandler * anim = CDefHandler::giveDef(customAnim);
|
for(int i=0; i * first->width() < owner->pos.w ; ++i)
|
||||||
|
|
||||||
for(int i=0; i * anim->width < owner->pos.w ; ++i)
|
|
||||||
{
|
{
|
||||||
for(int j=0; j * anim->height < owner->pos.h ; ++j)
|
for(int j=0; j * first->height() < owner->pos.h ; ++j)
|
||||||
{
|
{
|
||||||
BattleEffect be;
|
BattleEffect be;
|
||||||
be.effectID = ID;
|
be.effectID = ID;
|
||||||
be.anim = CDefHandler::giveDef(customAnim);
|
be.animation = animation;
|
||||||
if (Vflip)
|
|
||||||
{
|
|
||||||
for (auto & elem : be.anim->ourImages)
|
|
||||||
{
|
|
||||||
CSDL_Ext::VflipSurf(elem.bitmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
be.currentFrame = 0;
|
be.currentFrame = 0;
|
||||||
be.maxFrame = be.anim->ourImages.size();
|
|
||||||
be.x = i * anim->width + owner->pos.x;
|
be.x = i * first->width() + owner->pos.x;
|
||||||
be.y = j * anim->height + owner->pos.y;
|
be.y = j * first->height() + owner->pos.y;
|
||||||
be.position = BattleHex::INVALID;
|
be.position = BattleHex::INVALID;
|
||||||
|
|
||||||
owner->battleEffects.push_back(be);
|
owner->battleEffects.push_back(be);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
delete anim;
|
|
||||||
}
|
}
|
||||||
else // Effects targeted at a specific creature/hex.
|
else // Effects targeted at a specific creature/hex.
|
||||||
{
|
{
|
||||||
|
const CStack * destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(destTile, false);
|
||||||
|
Rect & tilePos = owner->bfield[destTile]->pos;
|
||||||
|
BattleEffect be;
|
||||||
|
be.effectID = ID;
|
||||||
|
be.animation = animation;
|
||||||
|
be.currentFrame = 0;
|
||||||
|
|
||||||
const CStack* destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(destTile, false);
|
|
||||||
Rect & tilePos = owner->bfield[destTile]->pos;
|
|
||||||
BattleEffect be;
|
|
||||||
be.effectID = ID;
|
|
||||||
be.anim = CDefHandler::giveDef(customAnim);
|
|
||||||
|
|
||||||
if (Vflip)
|
//todo: lightning anim frame count override
|
||||||
{
|
|
||||||
for (auto & elem : be.anim->ourImages)
|
|
||||||
{
|
|
||||||
CSDL_Ext::VflipSurf(elem.bitmap);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
be.currentFrame = 0;
|
|
||||||
be.maxFrame = be.anim->ourImages.size();
|
|
||||||
|
|
||||||
//todo: lightning anim frame count override
|
|
||||||
|
|
||||||
// if(effect == 1)
|
// if(effect == 1)
|
||||||
// be.maxFrame = 3;
|
// be.maxFrame = 3;
|
||||||
|
|
||||||
if(x == -1)
|
if(x == -1)
|
||||||
{
|
{
|
||||||
be.x = tilePos.x + tilePos.w/2 - be.anim->width/2;
|
be.x = tilePos.x + tilePos.w/2 - first->width()/2;
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
be.x = x;
|
||||||
|
}
|
||||||
|
|
||||||
|
if(y == -1)
|
||||||
|
{
|
||||||
|
if(alignToBottom)
|
||||||
|
be.y = tilePos.y + tilePos.h - first->height();
|
||||||
else
|
else
|
||||||
{
|
be.y = tilePos.y - first->height()/2;
|
||||||
be.x = x;
|
}
|
||||||
}
|
else
|
||||||
|
{
|
||||||
|
be.y = y;
|
||||||
|
}
|
||||||
|
|
||||||
if(y == -1)
|
// Correction for 2-hex creatures.
|
||||||
{
|
if(destStack != nullptr && destStack->doubleWide())
|
||||||
if(alignToBottom)
|
be.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
||||||
be.y = tilePos.y + tilePos.h - be.anim->height;
|
|
||||||
else
|
|
||||||
be.y = tilePos.y - be.anim->height/2;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
be.y = y;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Correction for 2-hex creatures.
|
//Indicate if effect should be drawn on top of everything or just on top of the hex
|
||||||
if (destStack != nullptr && destStack->doubleWide())
|
be.position = destTile;
|
||||||
be.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
|
||||||
|
|
||||||
//Indicate if effect should be drawn on top of everything or just on top of the hex
|
|
||||||
be.position = destTile;
|
|
||||||
|
|
||||||
owner->battleEffects.push_back(be);
|
|
||||||
|
|
||||||
|
owner->battleEffects.push_back(be);
|
||||||
}
|
}
|
||||||
//battleEffects
|
//battleEffects
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSpellEffectAnimation::nextFrame()
|
void CEffectAnimation::nextFrame()
|
||||||
{
|
{
|
||||||
//notice: there may be more than one effect in owner->battleEffects correcponding to this animation (ie. armageddon)
|
//notice: there may be more than one effect in owner->battleEffects correcponding to this animation (ie. armageddon)
|
||||||
for(auto & elem : owner->battleEffects)
|
for(auto & elem : owner->battleEffects)
|
||||||
@@ -1008,7 +1009,7 @@ void CSpellEffectAnimation::nextFrame()
|
|||||||
{
|
{
|
||||||
elem.currentFrame += AnimationControls::getSpellEffectSpeed() * GH.mainFPSmng->getElapsedMilliseconds() / 1000;
|
elem.currentFrame += AnimationControls::getSpellEffectSpeed() * GH.mainFPSmng->getElapsedMilliseconds() / 1000;
|
||||||
|
|
||||||
if(elem.currentFrame >= elem.maxFrame)
|
if(elem.currentFrame >= elem.animation->size())
|
||||||
{
|
{
|
||||||
endAnim();
|
endAnim();
|
||||||
break;
|
break;
|
||||||
@@ -1022,7 +1023,7 @@ void CSpellEffectAnimation::nextFrame()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CSpellEffectAnimation::endAnim()
|
void CEffectAnimation::endAnim()
|
||||||
{
|
{
|
||||||
CBattleAnimation::endAnim();
|
CBattleAnimation::endAnim();
|
||||||
|
|
||||||
@@ -1038,7 +1039,6 @@ void CSpellEffectAnimation::endAnim()
|
|||||||
|
|
||||||
for(auto & elem : toDel)
|
for(auto & elem : toDel)
|
||||||
{
|
{
|
||||||
delete elem->anim;
|
|
||||||
owner->battleEffects.erase(elem);
|
owner->battleEffects.erase(elem);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -208,16 +208,15 @@ public:
|
|||||||
void endAnim() override;
|
void endAnim() override;
|
||||||
|
|
||||||
//last two params only for catapult attacks
|
//last two params only for catapult attacks
|
||||||
CShootingAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest,
|
CShootingAnimation(CBattleInterface * _owner, const CStack * attacker, BattleHex _dest,
|
||||||
const CStack * _attacked, bool _catapult = false, int _catapultDmg = 0);
|
const CStack * _attacked, bool _catapult = false, int _catapultDmg = 0);
|
||||||
virtual ~CShootingAnimation(){};
|
virtual ~CShootingAnimation(){};
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class manages a spell effect animation
|
/// This class manages effect animation
|
||||||
class CSpellEffectAnimation : public CBattleAnimation
|
class CEffectAnimation : public CBattleAnimation
|
||||||
{
|
{
|
||||||
private:
|
private:
|
||||||
ui32 effect;
|
|
||||||
BattleHex destTile;
|
BattleHex destTile;
|
||||||
std::string customAnim;
|
std::string customAnim;
|
||||||
int x, y, dx, dy;
|
int x, y, dx, dy;
|
||||||
@@ -228,8 +227,7 @@ public:
|
|||||||
void nextFrame() override;
|
void nextFrame() override;
|
||||||
void endAnim() override;
|
void endAnim() override;
|
||||||
|
|
||||||
CSpellEffectAnimation(CBattleInterface * _owner, ui32 _effect, BattleHex _destTile, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
||||||
CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, int _x, int _y, int _dx = 0, int _dy = 0, bool _Vflip = false, bool _alignToBottom = false);
|
CEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip = false, bool _alignToBottom = false);
|
||||||
CSpellEffectAnimation(CBattleInterface * _owner, std::string _customAnim, BattleHex _destTile, bool _Vflip = false, bool _alignToBottom = false);
|
virtual ~CEffectAnimation(){};
|
||||||
virtual ~CSpellEffectAnimation(){};
|
|
||||||
};
|
};
|
||||||
|
@@ -23,6 +23,7 @@
|
|||||||
#include "../CPlayerInterface.h"
|
#include "../CPlayerInterface.h"
|
||||||
#include "../CVideoHandler.h"
|
#include "../CVideoHandler.h"
|
||||||
#include "../Graphics.h"
|
#include "../Graphics.h"
|
||||||
|
#include "../gui/CAnimation.h"
|
||||||
#include "../gui/CCursorHandler.h"
|
#include "../gui/CCursorHandler.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/SDL_Extensions.h"
|
#include "../gui/SDL_Extensions.h"
|
||||||
@@ -263,7 +264,10 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
|||||||
battleImage = hero1->type->heroClass->imageBattleMale;
|
battleImage = hero1->type->heroClass->imageBattleMale;
|
||||||
|
|
||||||
attackingHero = new CBattleHero(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this);
|
attackingHero = new CBattleHero(battleImage, false, hero1->tempOwner, hero1->tempOwner == curInt->playerID ? hero1 : nullptr, this);
|
||||||
attackingHero->pos = genRect(attackingHero->dh->ourImages[0].bitmap->h, attackingHero->dh->ourImages[0].bitmap->w, pos.x - 43, pos.y - 19);
|
|
||||||
|
IImage * img = attackingHero->animation->getImage(0, 0, true);
|
||||||
|
if(img)
|
||||||
|
attackingHero->pos = genRect(img->height(), img->width(), pos.x - 43, pos.y - 19);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -278,7 +282,10 @@ CBattleInterface::CBattleInterface(const CCreatureSet *army1, const CCreatureSet
|
|||||||
battleImage = hero2->type->heroClass->imageBattleMale;
|
battleImage = hero2->type->heroClass->imageBattleMale;
|
||||||
|
|
||||||
defendingHero = new CBattleHero(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this);
|
defendingHero = new CBattleHero(battleImage, true, hero2->tempOwner, hero2->tempOwner == curInt->playerID ? hero2 : nullptr, this);
|
||||||
defendingHero->pos = genRect(defendingHero->dh->ourImages[0].bitmap->h, defendingHero->dh->ourImages[0].bitmap->w, pos.x + 693, pos.y - 19);
|
|
||||||
|
IImage * img = defendingHero->animation->getImage(0, 0, true);
|
||||||
|
if(img)
|
||||||
|
defendingHero->pos = genRect(img->height(), img->width(), pos.x + 693, pos.y - 19);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -425,9 +432,6 @@ CBattleInterface::~CBattleInterface()
|
|||||||
for (auto & elem : creAnims)
|
for (auto & elem : creAnims)
|
||||||
delete elem.second;
|
delete elem.second;
|
||||||
|
|
||||||
for (auto & elem : idToProjectile)
|
|
||||||
delete elem.second;
|
|
||||||
|
|
||||||
for (auto & elem : idToObstacle)
|
for (auto & elem : idToObstacle)
|
||||||
delete elem.second;
|
delete elem.second;
|
||||||
|
|
||||||
@@ -999,20 +1003,21 @@ void CBattleInterface::newStack(const CStack *stack)
|
|||||||
|
|
||||||
void CBattleInterface::initStackProjectile(const CStack * stack)
|
void CBattleInterface::initStackProjectile(const CStack * stack)
|
||||||
{
|
{
|
||||||
CDefHandler *&projectile = idToProjectile[stack->getCreature()->idNumber];
|
const CCreature * creature;//creature whose shots should be loaded
|
||||||
|
if(stack->getCreature()->idNumber == CreatureID::ARROW_TOWERS)
|
||||||
const CCreature *creature;//creature whose shots should be loaded
|
|
||||||
if (stack->getCreature()->idNumber == CreatureID::ARROW_TOWERS)
|
|
||||||
creature = CGI->creh->creatures[siegeH->town->town->clientInfo.siegeShooter];
|
creature = CGI->creh->creatures[siegeH->town->town->clientInfo.siegeShooter];
|
||||||
else
|
else
|
||||||
creature = stack->getCreature();
|
creature = stack->getCreature();
|
||||||
|
|
||||||
projectile = CDefHandler::giveDef(creature->animation.projectileImageName);
|
std::shared_ptr<CAnimation> projectile = std::make_shared<CAnimation>(creature->animation.projectileImageName);
|
||||||
|
projectile->preload();
|
||||||
|
|
||||||
for (auto & elem : projectile->ourImages) //alpha transforming
|
if(projectile->size(1) != 0)
|
||||||
{
|
logAnim->error("Expected empty group 1 in stack projectile");
|
||||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
else
|
||||||
}
|
projectile->createFlippedGroup(0, 1);
|
||||||
|
|
||||||
|
idToProjectile[stack->getCreature()->idNumber] = projectile;
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::stackRemoved(int stackID)
|
void CBattleInterface::stackRemoved(int stackID)
|
||||||
@@ -1216,7 +1221,7 @@ void CBattleInterface::stackIsCatapulting(const CatapultAttack & ca)
|
|||||||
{
|
{
|
||||||
Point destPos = CClickableHex::getXYUnitAnim(attackInfo.destinationTile, nullptr, this) + Point(99, 120);
|
Point destPos = CClickableHex::getXYUnitAnim(attackInfo.destinationTile, nullptr, this) + Point(99, 120);
|
||||||
|
|
||||||
addNewAnim(new CSpellEffectAnimation(this, "SGEXPL.DEF", destPos.x, destPos.y));
|
addNewAnim(new CEffectAnimation(this, "SGEXPL.DEF", destPos.x, destPos.y));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1304,20 +1309,23 @@ void CBattleInterface::spellCast(const BattleSpellCast *sc)
|
|||||||
|
|
||||||
std::string animToDisplay = spell.animationInfo.selectProjectile(angle);
|
std::string animToDisplay = spell.animationInfo.selectProjectile(angle);
|
||||||
|
|
||||||
if (!animToDisplay.empty())
|
if(!animToDisplay.empty())
|
||||||
{
|
{
|
||||||
|
//TODO: calculate inside CEffectAnimation
|
||||||
|
std::shared_ptr<CAnimation> tmp = std::make_shared<CAnimation>(animToDisplay);
|
||||||
|
tmp->load(0, 0);
|
||||||
|
IImage * first = tmp->getImage(0, 0);
|
||||||
|
|
||||||
//displaying animation
|
//displaying animation
|
||||||
CDefEssential *animDef = CDefHandler::giveDefEss(animToDisplay);
|
|
||||||
double diffX = (destcoord.x - srccoord.x)*(destcoord.x - srccoord.x);
|
double diffX = (destcoord.x - srccoord.x)*(destcoord.x - srccoord.x);
|
||||||
double diffY = (destcoord.y - srccoord.y)*(destcoord.y - srccoord.y);
|
double diffY = (destcoord.y - srccoord.y)*(destcoord.y - srccoord.y);
|
||||||
double distance = sqrt(diffX + diffY);
|
double distance = sqrt(diffX + diffY);
|
||||||
|
|
||||||
int steps = distance / AnimationControls::getSpellEffectSpeed() + 1;
|
int steps = distance / AnimationControls::getSpellEffectSpeed() + 1;
|
||||||
int dx = (destcoord.x - srccoord.x - animDef->ourImages[0].bitmap->w)/steps;
|
int dx = (destcoord.x - srccoord.x - first->width())/steps;
|
||||||
int dy = (destcoord.y - srccoord.y - animDef->ourImages[0].bitmap->h)/steps;
|
int dy = (destcoord.y - srccoord.y - first->height())/steps;
|
||||||
|
|
||||||
delete animDef;
|
addNewAnim(new CEffectAnimation(this, animToDisplay, srccoord.x, srccoord.y, dx, dy, Vflip));
|
||||||
addNewAnim(new CSpellEffectAnimation(this, animToDisplay, srccoord.x, srccoord.y, dx, dy, Vflip));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
waitForAnims();
|
waitForAnims();
|
||||||
@@ -1349,8 +1357,8 @@ void CBattleInterface::spellCast(const BattleSpellCast *sc)
|
|||||||
{
|
{
|
||||||
Point leftHero = Point(15, 30) + pos;
|
Point leftHero = Point(15, 30) + pos;
|
||||||
Point rightHero = Point(755, 30) + pos;
|
Point rightHero = Point(755, 30) + pos;
|
||||||
addNewAnim(new CSpellEffectAnimation(this, sc->side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero.x, leftHero.y, 0, 0, false));
|
addNewAnim(new CEffectAnimation(this, sc->side ? "SP07_A.DEF" : "SP07_B.DEF", leftHero.x, leftHero.y, 0, 0, false));
|
||||||
addNewAnim(new CSpellEffectAnimation(this, sc->side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero.x, rightHero.y, 0, 0, false));
|
addNewAnim(new CEffectAnimation(this, sc->side ? "SP07_B.DEF" : "SP07_A.DEF", rightHero.x, rightHero.y, 0, 0, false));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1413,9 +1421,11 @@ void CBattleInterface::castThisSpell(SpellID spellID)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::displayEffect(ui32 effect, int destTile)
|
void CBattleInterface::displayEffect(ui32 effect, BattleHex destTile)
|
||||||
{
|
{
|
||||||
addNewAnim(new CSpellEffectAnimation(this, effect, destTile, 0, 0, false));
|
std::string customAnim = graphics->battleACToDef[effect][0];
|
||||||
|
|
||||||
|
addNewAnim(new CEffectAnimation(this, customAnim, destTile));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CBattleInterface::displaySpellAnimation(const CSpell::TAnimation & animation, BattleHex destinationTile)
|
void CBattleInterface::displaySpellAnimation(const CSpell::TAnimation & animation, BattleHex destinationTile)
|
||||||
@@ -1426,7 +1436,7 @@ void CBattleInterface::displaySpellAnimation(const CSpell::TAnimation & animatio
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
addNewAnim(new CSpellEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
addNewAnim(new CEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2732,7 +2742,7 @@ void CBattleInterface::obstaclePlaced(const CObstacleInstance & oi)
|
|||||||
//we assume here that effect graphics have the same size as the usual obstacle image
|
//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
|
// -> if we know how to blit obstacle, let's blit the effect in the same place
|
||||||
Point whereTo = getObstaclePosition(getObstacleImage(oi), oi);
|
Point whereTo = getObstaclePosition(getObstacleImage(oi), oi);
|
||||||
addNewAnim(new CSpellEffectAnimation(this, defname, whereTo.x, whereTo.y));
|
addNewAnim(new CEffectAnimation(this, defname, whereTo.x, whereTo.y));
|
||||||
|
|
||||||
//TODO we need to wait after playing sound till it's finished, otherwise it overlaps and sounds really bad
|
//TODO we need to wait after playing sound till it's finished, otherwise it overlaps and sounds really bad
|
||||||
//CCS->soundh->playSound(sound);
|
//CCS->soundh->playSound(sound);
|
||||||
@@ -3166,23 +3176,18 @@ void CBattleInterface::showProjectiles(SDL_Surface *to)
|
|||||||
continue; // wait...
|
continue; // wait...
|
||||||
}
|
}
|
||||||
|
|
||||||
SDL_Surface *image = idToProjectile[it->creID]->ourImages[it->frameNum].bitmap;
|
size_t group = it->reverse ? 1 : 0;
|
||||||
|
IImage * image = idToProjectile[it->creID]->getImage(it->frameNum, group, true);
|
||||||
|
|
||||||
SDL_Rect dst;
|
if(image)
|
||||||
dst.h = image->h;
|
{
|
||||||
dst.w = image->w;
|
SDL_Rect dst;
|
||||||
dst.x = it->x - dst.w / 2;
|
dst.h = image->height();
|
||||||
dst.y = it->y - dst.h / 2;
|
dst.w = image->width();
|
||||||
|
dst.x = it->x - dst.w / 2;
|
||||||
|
dst.y = it->y - dst.h / 2;
|
||||||
|
|
||||||
if (it->reverse)
|
image->draw(to, &dst, nullptr);
|
||||||
{
|
|
||||||
SDL_Surface *rev = CSDL_Ext::verticalFlip(image);
|
|
||||||
CSDL_Ext::blit8bppAlphaTo24bpp(rev, nullptr, to, &dst);
|
|
||||||
SDL_FreeSurface(rev);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
CSDL_Ext::blit8bppAlphaTo24bpp(image, nullptr, to, &dst);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update projectile
|
// Update projectile
|
||||||
@@ -3200,7 +3205,7 @@ void CBattleInterface::showProjectiles(SDL_Surface *to)
|
|||||||
it->y = it->catapultInfo->calculateY(it->x);
|
it->y = it->catapultInfo->calculateY(it->x);
|
||||||
|
|
||||||
++(it->frameNum);
|
++(it->frameNum);
|
||||||
it->frameNum %= idToProjectile[it->creID]->ourImages.size();
|
it->frameNum %= idToProjectile[it->creID]->size(0);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -3368,11 +3373,13 @@ void CBattleInterface::showBattleEffects(SDL_Surface *to, const std::vector<cons
|
|||||||
for (auto & elem : battleEffects)
|
for (auto & elem : battleEffects)
|
||||||
{
|
{
|
||||||
int currentFrame = floor(elem->currentFrame);
|
int currentFrame = floor(elem->currentFrame);
|
||||||
currentFrame %= elem->anim->ourImages.size();
|
currentFrame %= elem->animation->size();
|
||||||
|
|
||||||
SDL_Surface *bitmapToBlit = elem->anim->ourImages[currentFrame].bitmap;
|
IImage * img = elem->animation->getImage(currentFrame);
|
||||||
SDL_Rect temp_rect = genRect(bitmapToBlit->h, bitmapToBlit->w, elem->x, elem->y);
|
|
||||||
SDL_BlitSurface(bitmapToBlit, nullptr, to, &temp_rect);
|
SDL_Rect temp_rect = genRect(img->height(), img->width(), elem->x, elem->y);
|
||||||
|
|
||||||
|
img->draw(to, &temp_rect, nullptr);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -48,6 +48,7 @@ struct BattleHex;
|
|||||||
struct InfoAboutHero;
|
struct InfoAboutHero;
|
||||||
struct BattleAction;
|
struct BattleAction;
|
||||||
class CBattleGameInterface;
|
class CBattleGameInterface;
|
||||||
|
class CAnimation;
|
||||||
|
|
||||||
/// 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
|
||||||
@@ -67,8 +68,7 @@ struct BattleEffect
|
|||||||
{
|
{
|
||||||
int x, y; //position on the screen
|
int x, y; //position on the screen
|
||||||
float currentFrame;
|
float currentFrame;
|
||||||
int maxFrame;
|
std::shared_ptr<CAnimation> animation;
|
||||||
CDefHandler *anim; //animation to display
|
|
||||||
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
|
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
|
||||||
BattleHex position; //Indicates if effect which hex the effect is drawn on
|
BattleHex position; //Indicates if effect which hex the effect is drawn on
|
||||||
};
|
};
|
||||||
@@ -120,6 +120,7 @@ class CBattleInterface : public CIntObject
|
|||||||
};
|
};
|
||||||
private:
|
private:
|
||||||
SDL_Surface *background, *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral, *cellBorders, *backgroundWithHexes;
|
SDL_Surface *background, *menu, *amountNormal, *amountNegative, *amountPositive, *amountEffNeutral, *cellBorders, *backgroundWithHexes;
|
||||||
|
|
||||||
CButton *bOptions, *bSurrender, *bFlee, *bAutofight, *bSpell,
|
CButton *bOptions, *bSurrender, *bFlee, *bAutofight, *bSpell,
|
||||||
* bWait, *bDefence, *bConsoleUp, *bConsoleDown, *btactNext, *btactEnd;
|
* bWait, *bDefence, *bConsoleUp, *bConsoleDown, *btactNext, *btactEnd;
|
||||||
CBattleConsole *console;
|
CBattleConsole *console;
|
||||||
@@ -128,7 +129,9 @@ private:
|
|||||||
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
const CCreatureSet *army1, *army2; //copy of initial armies (for result window)
|
||||||
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
const CGHeroInstance *attackingHeroInstance, *defendingHeroInstance;
|
||||||
std::map<int, CCreatureAnimation *> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
std::map<int, CCreatureAnimation *> creAnims; //animations of creatures from fighting armies (order by BattleInfo's stacks' ID)
|
||||||
std::map<int, CDefHandler *> idToProjectile; //projectiles of creatures (creatureID, defhandler)
|
|
||||||
|
std::map<int, std::shared_ptr<CAnimation>> idToProjectile;
|
||||||
|
|
||||||
std::map<int, CDefHandler *> idToObstacle; //obstacles located on the battlefield
|
std::map<int, CDefHandler *> idToObstacle; //obstacles located on the battlefield
|
||||||
std::map<int, SDL_Surface *> idToAbsoluteObstacle; //obstacles located on the battlefield
|
std::map<int, SDL_Surface *> idToAbsoluteObstacle; //obstacles located on the battlefield
|
||||||
|
|
||||||
@@ -340,7 +343,7 @@ public:
|
|||||||
void spellCast(const BattleSpellCast *sc); //called when a hero casts a spell
|
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 battleStacksEffectsSet(const SetStackEffect & sse); //called when a specific effect is set to stacks
|
||||||
void castThisSpell(SpellID spellID); //called when player has chosen a spell from spellbook
|
void castThisSpell(SpellID spellID); //called when player has chosen a spell from spellbook
|
||||||
void displayEffect(ui32 effect, int destTile); //displays custom effect on the battlefield
|
void displayEffect(ui32 effect, BattleHex destTile); //displays custom effect on the battlefield
|
||||||
|
|
||||||
void displaySpellCast(SpellID spellID, BattleHex destinationTile); //displays spell`s cast animation
|
void displaySpellCast(SpellID spellID, BattleHex destinationTile); //displays spell`s cast animation
|
||||||
void displaySpellEffect(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation
|
void displaySpellEffect(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation
|
||||||
@@ -376,7 +379,7 @@ public:
|
|||||||
|
|
||||||
friend class CBattleResultWindow;
|
friend class CBattleResultWindow;
|
||||||
friend class CBattleHero;
|
friend class CBattleHero;
|
||||||
friend class CSpellEffectAnimation;
|
friend class CEffectAnimation;
|
||||||
friend class CBattleStackAnimation;
|
friend class CBattleStackAnimation;
|
||||||
friend class CReverseAnimation;
|
friend class CReverseAnimation;
|
||||||
friend class CDefenceAnimation;
|
friend class CDefenceAnimation;
|
||||||
|
@@ -13,13 +13,13 @@
|
|||||||
#include "CBattleInterface.h"
|
#include "CBattleInterface.h"
|
||||||
|
|
||||||
#include "../CBitmapHandler.h"
|
#include "../CBitmapHandler.h"
|
||||||
#include "../CDefHandler.h"
|
|
||||||
#include "../CGameInfo.h"
|
#include "../CGameInfo.h"
|
||||||
#include "../CMessage.h"
|
#include "../CMessage.h"
|
||||||
#include "../CMusicHandler.h"
|
#include "../CMusicHandler.h"
|
||||||
#include "../CPlayerInterface.h"
|
#include "../CPlayerInterface.h"
|
||||||
#include "../CVideoHandler.h"
|
#include "../CVideoHandler.h"
|
||||||
#include "../Graphics.h"
|
#include "../Graphics.h"
|
||||||
|
#include "../gui/CAnimation.h"
|
||||||
#include "../gui/CCursorHandler.h"
|
#include "../gui/CCursorHandler.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
#include "../gui/SDL_Extensions.h"
|
#include "../gui/SDL_Extensions.h"
|
||||||
@@ -129,13 +129,18 @@ CBattleConsole::CBattleConsole() : lastShown(-1), alterTxt(""), whoSetAlter(0)
|
|||||||
|
|
||||||
void CBattleHero::show(SDL_Surface * to)
|
void CBattleHero::show(SDL_Surface * to)
|
||||||
{
|
{
|
||||||
|
IImage * flagFrame = flagAnimation->getImage(flagAnim, 0, true);
|
||||||
|
|
||||||
|
if(!flagFrame)
|
||||||
|
return;
|
||||||
|
|
||||||
//animation of flag
|
//animation of flag
|
||||||
SDL_Rect temp_rect;
|
SDL_Rect temp_rect;
|
||||||
if(flip)
|
if(flip)
|
||||||
{
|
{
|
||||||
temp_rect = genRect(
|
temp_rect = genRect(
|
||||||
flag->ourImages[flagAnim].bitmap->h,
|
flagFrame->height(),
|
||||||
flag->ourImages[flagAnim].bitmap->w,
|
flagFrame->width(),
|
||||||
pos.x + 61,
|
pos.x + 61,
|
||||||
pos.y + 39);
|
pos.y + 39);
|
||||||
|
|
||||||
@@ -143,28 +148,30 @@ void CBattleHero::show(SDL_Surface * to)
|
|||||||
else
|
else
|
||||||
{
|
{
|
||||||
temp_rect = genRect(
|
temp_rect = genRect(
|
||||||
flag->ourImages[flagAnim].bitmap->h,
|
flagFrame->height(),
|
||||||
flag->ourImages[flagAnim].bitmap->w,
|
flagFrame->width(),
|
||||||
pos.x + 72,
|
pos.x + 72,
|
||||||
pos.y + 39);
|
pos.y + 39);
|
||||||
}
|
}
|
||||||
CSDL_Ext::blit8bppAlphaTo24bpp(
|
|
||||||
flag->ourImages[flagAnim].bitmap,
|
flagFrame->draw(screen, &temp_rect, nullptr); //FIXME: why screen?
|
||||||
nullptr,
|
|
||||||
screen,
|
|
||||||
&temp_rect);
|
|
||||||
|
|
||||||
//animation of hero
|
//animation of hero
|
||||||
SDL_Rect rect = pos;
|
SDL_Rect rect = pos;
|
||||||
CSDL_Ext::blit8bppAlphaTo24bpp(dh->ourImages[currentFrame].bitmap, nullptr, to, &rect);
|
|
||||||
|
|
||||||
if ( ++animCount == 4 )
|
IImage * heroFrame = animation->getImage(currentFrame, phase, true);
|
||||||
|
if(!heroFrame)
|
||||||
|
return;
|
||||||
|
|
||||||
|
heroFrame->draw(to, &rect, nullptr);
|
||||||
|
|
||||||
|
if(++animCount >= 4)
|
||||||
{
|
{
|
||||||
animCount = 0;
|
animCount = 0;
|
||||||
if ( ++flagAnim >= flag->ourImages.size())
|
if(++flagAnim >= flagAnimation->size(0))
|
||||||
flagAnim = 0;
|
flagAnim = 0;
|
||||||
|
|
||||||
if ( ++currentFrame >= lastFrame)
|
if(++currentFrame >= lastFrame)
|
||||||
switchToNextPhase();
|
switchToNextPhase();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -190,7 +197,13 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
|
|||||||
if(myOwner->spellDestSelectMode) //we are casting a spell
|
if(myOwner->spellDestSelectMode) //we are casting a spell
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if(myHero != nullptr && !down && myOwner->myTurn && myOwner->getCurrentPlayerInterface()->cb->battleCanCastSpell(myHero, ECastingMode::HERO_CASTING) == ESpellCastProblem::OK) //check conditions
|
if(boost::logic::indeterminate(down))
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(!myHero || down || !myOwner->myTurn)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(myOwner->getCurrentPlayerInterface()->cb->battleCanCastSpell(myHero, ECastingMode::HERO_CASTING) == ESpellCastProblem::OK) //check conditions
|
||||||
{
|
{
|
||||||
for(int it=0; it<GameConstants::BFIELD_SIZE; ++it) //do nothing when any hex is hovered - hero's animation overlaps battlefield
|
for(int it=0; it<GameConstants::BFIELD_SIZE; ++it) //do nothing when any hex is hovered - hero's animation overlaps battlefield
|
||||||
{
|
{
|
||||||
@@ -205,6 +218,9 @@ void CBattleHero::clickLeft(tribool down, bool previousState)
|
|||||||
|
|
||||||
void CBattleHero::clickRight(tribool down, bool previousState)
|
void CBattleHero::clickRight(tribool down, bool previousState)
|
||||||
{
|
{
|
||||||
|
if(boost::logic::indeterminate(down))
|
||||||
|
return;
|
||||||
|
|
||||||
Point windowPosition;
|
Point windowPosition;
|
||||||
windowPosition.x = (!flip) ? myOwner->pos.topLeft().x + 1 : myOwner->pos.topRight().x - 79;
|
windowPosition.x = (!flip) ? myOwner->pos.topLeft().x + 1 : myOwner->pos.topRight().x - 79;
|
||||||
windowPosition.y = myOwner->pos.y + 135;
|
windowPosition.y = myOwner->pos.y + 135;
|
||||||
@@ -220,24 +236,19 @@ void CBattleHero::clickRight(tribool down, bool previousState)
|
|||||||
|
|
||||||
void CBattleHero::switchToNextPhase()
|
void CBattleHero::switchToNextPhase()
|
||||||
{
|
{
|
||||||
if (phase != nextPhase)
|
if(phase != nextPhase)
|
||||||
{
|
{
|
||||||
phase = nextPhase;
|
phase = nextPhase;
|
||||||
|
|
||||||
//find first and last frames of our animation
|
firstFrame = 0;
|
||||||
for (firstFrame = 0;
|
|
||||||
firstFrame < dh->ourImages.size() && dh->ourImages[firstFrame].groupNumber != phase;
|
|
||||||
firstFrame++);
|
|
||||||
|
|
||||||
for (lastFrame = firstFrame;
|
lastFrame = animation->size(phase);
|
||||||
lastFrame < dh->ourImages.size() && dh->ourImages[lastFrame].groupNumber == phase;
|
|
||||||
lastFrame++);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
currentFrame = firstFrame;
|
currentFrame = firstFrame;
|
||||||
}
|
}
|
||||||
|
|
||||||
CBattleHero::CBattleHero(const std::string & defName, bool flipG, PlayerColor player, const CGHeroInstance * hero, const CBattleInterface * owner):
|
CBattleHero::CBattleHero(const std::string & animationPath, bool flipG, PlayerColor player, const CGHeroInstance * hero, const CBattleInterface * owner):
|
||||||
flip(flipG),
|
flip(flipG),
|
||||||
myHero(hero),
|
myHero(hero),
|
||||||
myOwner(owner),
|
myOwner(owner),
|
||||||
@@ -246,39 +257,25 @@ CBattleHero::CBattleHero(const std::string & defName, bool flipG, PlayerColor pl
|
|||||||
flagAnim(0),
|
flagAnim(0),
|
||||||
animCount(0)
|
animCount(0)
|
||||||
{
|
{
|
||||||
dh = CDefHandler::giveDef( defName );
|
animation = std::make_shared<CAnimation>(animationPath);
|
||||||
for(auto & elem : dh->ourImages) //transforming images
|
animation->preload();
|
||||||
{
|
if(flipG)
|
||||||
if(flip)
|
animation->verticalFlip();
|
||||||
{
|
|
||||||
SDL_Surface * hlp = CSDL_Ext::verticalFlip(elem.bitmap);
|
|
||||||
SDL_FreeSurface(elem.bitmap);
|
|
||||||
elem.bitmap = hlp;
|
|
||||||
}
|
|
||||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
|
||||||
}
|
|
||||||
|
|
||||||
if(flip)
|
if(flip)
|
||||||
flag = CDefHandler::giveDef("CMFLAGR.DEF");
|
flagAnimation = std::make_shared<CAnimation>("CMFLAGR");
|
||||||
else
|
else
|
||||||
flag = CDefHandler::giveDef("CMFLAGL.DEF");
|
flagAnimation = std::make_shared<CAnimation>("CMFLAGL");
|
||||||
|
|
||||||
|
flagAnimation->preload();
|
||||||
|
flagAnimation->playerColored(player);
|
||||||
|
|
||||||
//coloring flag and adding transparency
|
|
||||||
for(auto & elem : flag->ourImages)
|
|
||||||
{
|
|
||||||
CSDL_Ext::alphaTransform(elem.bitmap);
|
|
||||||
graphics->blueToPlayersAdv(elem.bitmap, player);
|
|
||||||
}
|
|
||||||
addUsedEvents(LCLICK | RCLICK | HOVER);
|
addUsedEvents(LCLICK | RCLICK | HOVER);
|
||||||
|
|
||||||
switchToNextPhase();
|
switchToNextPhase();
|
||||||
}
|
}
|
||||||
|
|
||||||
CBattleHero::~CBattleHero()
|
CBattleHero::~CBattleHero() = default;
|
||||||
{
|
|
||||||
delete dh;
|
|
||||||
delete flag;
|
|
||||||
}
|
|
||||||
|
|
||||||
CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner)
|
CBattleOptionsWindow::CBattleOptionsWindow(const SDL_Rect & position, CBattleInterface *owner)
|
||||||
{
|
{
|
||||||
|
@@ -14,7 +14,6 @@
|
|||||||
#include "../windows/CWindowObject.h"
|
#include "../windows/CWindowObject.h"
|
||||||
|
|
||||||
struct SDL_Surface;
|
struct SDL_Surface;
|
||||||
class CDefHandler;
|
|
||||||
class CGHeroInstance;
|
class CGHeroInstance;
|
||||||
class CBattleInterface;
|
class CBattleInterface;
|
||||||
class CPicture;
|
class CPicture;
|
||||||
@@ -53,19 +52,24 @@ class CBattleHero : public CIntObject
|
|||||||
void switchToNextPhase();
|
void switchToNextPhase();
|
||||||
public:
|
public:
|
||||||
bool flip; //false if it's attacking hero, true otherwise
|
bool flip; //false if it's attacking hero, true otherwise
|
||||||
CDefHandler *dh, *flag; //animation and flag
|
|
||||||
|
std::shared_ptr<CAnimation> animation;
|
||||||
|
std::shared_ptr<CAnimation> flagAnimation;
|
||||||
|
|
||||||
const CGHeroInstance * myHero; //this animation's hero instance
|
const CGHeroInstance * myHero; //this animation's hero instance
|
||||||
const CBattleInterface * myOwner; //battle interface to which this animation is assigned
|
const CBattleInterface * myOwner; //battle interface to which this animation is assigned
|
||||||
int phase; //stage of animation
|
int phase; //stage of animation
|
||||||
int nextPhase; //stage of animation to be set after current phase is fully displayed
|
int nextPhase; //stage of animation to be set after current phase is fully displayed
|
||||||
int currentFrame, firstFrame, lastFrame; //frame of animation
|
int currentFrame, firstFrame, lastFrame; //frame of animation
|
||||||
ui8 flagAnim, animCount; //for flag animation
|
|
||||||
|
size_t flagAnim;
|
||||||
|
ui8 animCount; //for flag animation
|
||||||
void show(SDL_Surface * to) override; //prints next frame of animation to to
|
void show(SDL_Surface * to) override; //prints next frame of animation to to
|
||||||
void setPhase(int newPhase); //sets phase of hero animation
|
void setPhase(int newPhase); //sets phase of hero animation
|
||||||
void hover(bool on) override;
|
void hover(bool on) override;
|
||||||
void clickLeft(tribool down, bool previousState) override; //call-in
|
void clickLeft(tribool down, bool previousState) override; //call-in
|
||||||
void clickRight(tribool down, bool previousState) override; //call-in
|
void clickRight(tribool down, bool previousState) override; //call-in
|
||||||
CBattleHero(const std::string &defName, bool filpG, PlayerColor player, const CGHeroInstance *hero, const CBattleInterface *owner);
|
CBattleHero(const std::string & animationPath, bool filpG, PlayerColor player, const CGHeroInstance * hero, const CBattleInterface * owner);
|
||||||
~CBattleHero();
|
~CBattleHero();
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@@ -10,14 +10,10 @@
|
|||||||
#include "StdInc.h"
|
#include "StdInc.h"
|
||||||
#include "CCreatureAnimation.h"
|
#include "CCreatureAnimation.h"
|
||||||
|
|
||||||
#include "../../lib/vcmi_endian.h"
|
|
||||||
#include "../../lib/CConfigHandler.h"
|
#include "../../lib/CConfigHandler.h"
|
||||||
#include "../../lib/CCreatureHandler.h"
|
#include "../../lib/CCreatureHandler.h"
|
||||||
#include "../../lib/filesystem/Filesystem.h"
|
|
||||||
#include "../../lib/filesystem/CBinaryReader.h"
|
|
||||||
#include "../../lib/filesystem/CMemoryStream.h"
|
|
||||||
|
|
||||||
#include "../gui/SDL_Pixels.h"
|
#include "../gui/SDL_Extensions.h"
|
||||||
|
|
||||||
static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 };
|
static const SDL_Color creatureBlueBorder = { 0, 255, 255, 255 };
|
||||||
static const SDL_Color creatureGoldBorder = { 255, 255, 0, 255 };
|
static const SDL_Color creatureGoldBorder = { 255, 255, 0, 255 };
|
||||||
@@ -142,60 +138,43 @@ void CCreatureAnimation::setType(CCreatureAnim::EAnimType type)
|
|||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
|
|
||||||
CCreatureAnimation::CCreatureAnimation(std::string name, TSpeedController controller)
|
CCreatureAnimation::CCreatureAnimation(const std::string & name_, TSpeedController controller)
|
||||||
: defName(name),
|
: name(name_),
|
||||||
speed(0.1),
|
speed(0.1),
|
||||||
currentFrame(0),
|
currentFrame(0),
|
||||||
elapsedTime(0),
|
elapsedTime(0),
|
||||||
type(CCreatureAnim::HOLDING),
|
type(CCreatureAnim::HOLDING),
|
||||||
border(CSDL_Ext::makeColor(0, 0, 0, 0)),
|
border(CSDL_Ext::makeColor(0, 0, 0, 0)),
|
||||||
speedController(controller),
|
speedController(controller),
|
||||||
once(false)
|
once(false)
|
||||||
{
|
{
|
||||||
// separate block to avoid accidental use of "data" after it was moved into "pixelData"
|
forward = std::make_shared<CAnimation>(name_);
|
||||||
{
|
reverse = std::make_shared<CAnimation>(name_);
|
||||||
ResourceID resID(std::string("SPRITES/") + name, EResType::ANIMATION);
|
|
||||||
|
|
||||||
auto data = CResourceHandler::get()->load(resID)->readAll();
|
//todo: optimize
|
||||||
|
forward->preload();
|
||||||
pixelData = std::move(data.first);
|
reverse->preload();
|
||||||
pixelDataSize = data.second;
|
|
||||||
}
|
|
||||||
|
|
||||||
CMemoryStream stm(pixelData.get(), pixelDataSize);
|
|
||||||
|
|
||||||
CBinaryReader reader(&stm);
|
|
||||||
|
|
||||||
reader.readInt32(); // def type, unused
|
|
||||||
|
|
||||||
fullWidth = reader.readInt32();
|
|
||||||
fullHeight = reader.readInt32();
|
|
||||||
|
|
||||||
int totalBlocks = reader.readInt32();
|
|
||||||
|
|
||||||
for (auto & elem : palette)
|
|
||||||
{
|
|
||||||
elem.r = reader.readUInt8();
|
|
||||||
elem.g = reader.readUInt8();
|
|
||||||
elem.b = reader.readUInt8();
|
|
||||||
elem.a = SDL_ALPHA_OPAQUE;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (int i=0; i<totalBlocks; i++)
|
|
||||||
{
|
|
||||||
int groupID = reader.readInt32();
|
|
||||||
|
|
||||||
int totalInBlock = reader.readInt32();
|
|
||||||
|
|
||||||
reader.skip(4 + 4 + 13 * totalInBlock); // some unused data
|
|
||||||
|
|
||||||
for (int j=0; j<totalInBlock; j++)
|
|
||||||
dataOffsets[groupID].push_back(reader.readUInt32());
|
|
||||||
}
|
|
||||||
|
|
||||||
// if necessary, add one frame into vcmi-only group DEAD
|
// if necessary, add one frame into vcmi-only group DEAD
|
||||||
if (dataOffsets.count(CCreatureAnim::DEAD) == 0)
|
if(forward->size(CCreatureAnim::DEAD) == 0)
|
||||||
dataOffsets[CCreatureAnim::DEAD].push_back(dataOffsets[CCreatureAnim::DEATH].back());
|
{
|
||||||
|
forward->duplicateImage(CCreatureAnim::DEATH, forward->size(CCreatureAnim::DEATH)-1, CCreatureAnim::DEAD);
|
||||||
|
reverse->duplicateImage(CCreatureAnim::DEATH, reverse->size(CCreatureAnim::DEATH)-1, CCreatureAnim::DEAD);
|
||||||
|
}
|
||||||
|
|
||||||
|
//TODO: get dimensions form CAnimation
|
||||||
|
IImage * first = forward->getImage(0, type, true);
|
||||||
|
|
||||||
|
if(!first)
|
||||||
|
{
|
||||||
|
fullWidth = 0;
|
||||||
|
fullHeight = 0;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
fullWidth = first->width();
|
||||||
|
fullHeight = first->height();
|
||||||
|
|
||||||
|
reverse->verticalFlip();
|
||||||
|
|
||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
@@ -285,142 +264,35 @@ static SDL_Color addColors(const SDL_Color & base, const SDL_Color & over)
|
|||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::array<SDL_Color, 8> CCreatureAnimation::genSpecialPalette()
|
void CCreatureAnimation::genBorderPalette(IImage::BorderPallete & target)
|
||||||
{
|
{
|
||||||
std::array<SDL_Color, 8> ret;
|
target[0] = genBorderColor(getBorderStrength(elapsedTime), border);
|
||||||
|
target[1] = addColors(genShadow(128), genBorderColor(getBorderStrength(elapsedTime), border));
|
||||||
ret[0] = genShadow(0);
|
target[2] = addColors(genShadow(64), genBorderColor(getBorderStrength(elapsedTime), border));
|
||||||
ret[1] = genShadow(64);
|
|
||||||
ret[2] = genShadow(128);//unused
|
|
||||||
ret[3] = genShadow(128);//unused
|
|
||||||
ret[4] = genShadow(128);
|
|
||||||
ret[5] = genBorderColor(getBorderStrength(elapsedTime), border);
|
|
||||||
ret[6] = addColors(genShadow(128), genBorderColor(getBorderStrength(elapsedTime), border));
|
|
||||||
ret[7] = addColors(genShadow(64), genBorderColor(getBorderStrength(elapsedTime), border));
|
|
||||||
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int bpp>
|
|
||||||
void CCreatureAnimation::nextFrameT(SDL_Surface * dest, bool rotate)
|
|
||||||
{
|
|
||||||
assert(dataOffsets.count(type) && dataOffsets.at(type).size() > size_t(currentFrame));
|
|
||||||
|
|
||||||
ui32 offset = dataOffsets.at(type).at(floor(currentFrame));
|
|
||||||
|
|
||||||
CMemoryStream stm(pixelData.get(), pixelDataSize);
|
|
||||||
|
|
||||||
CBinaryReader reader(&stm);
|
|
||||||
|
|
||||||
reader.getStream()->seek(offset);
|
|
||||||
|
|
||||||
reader.readUInt32(); // unused, size of pixel data for this frame
|
|
||||||
const ui32 defType2 = reader.readUInt32();
|
|
||||||
const ui32 fullWidth = reader.readUInt32();
|
|
||||||
/*const ui32 fullHeight =*/ reader.readUInt32();
|
|
||||||
const ui32 spriteWidth = reader.readUInt32();
|
|
||||||
const ui32 spriteHeight = reader.readUInt32();
|
|
||||||
const int leftMargin = reader.readInt32();
|
|
||||||
const int topMargin = reader.readInt32();
|
|
||||||
|
|
||||||
const int rightMargin = fullWidth - spriteWidth - leftMargin;
|
|
||||||
//const int bottomMargin = fullHeight - spriteHeight - topMargin;
|
|
||||||
|
|
||||||
const size_t baseOffset = reader.getStream()->tell();
|
|
||||||
|
|
||||||
assert(defType2 == 1);
|
|
||||||
UNUSED(defType2);
|
|
||||||
|
|
||||||
auto specialPalette = genSpecialPalette();
|
|
||||||
|
|
||||||
for (ui32 i=0; i<spriteHeight; i++)
|
|
||||||
{
|
|
||||||
//NOTE: if this loop will be optimized to skip empty lines - recheck this read access
|
|
||||||
ui8 * lineData = pixelData.get() + baseOffset + reader.readUInt32();
|
|
||||||
|
|
||||||
size_t destX = pos.x;
|
|
||||||
if (rotate)
|
|
||||||
destX += rightMargin + spriteWidth - 1;
|
|
||||||
else
|
|
||||||
destX += leftMargin;
|
|
||||||
|
|
||||||
size_t destY = pos.y + topMargin + i;
|
|
||||||
size_t currentOffset = 0;
|
|
||||||
size_t totalRowLength = 0;
|
|
||||||
|
|
||||||
while (totalRowLength < spriteWidth)
|
|
||||||
{
|
|
||||||
ui8 type = lineData[currentOffset++];
|
|
||||||
ui32 length = lineData[currentOffset++] + 1;
|
|
||||||
|
|
||||||
if (type==0xFF)//Raw data
|
|
||||||
{
|
|
||||||
for (size_t j=0; j<length; j++)
|
|
||||||
putPixelAt<bpp>(dest, destX + (rotate?(-j):(j)), destY, lineData[currentOffset + j], specialPalette);
|
|
||||||
|
|
||||||
currentOffset += length;
|
|
||||||
}
|
|
||||||
else// RLE
|
|
||||||
{
|
|
||||||
if (type != 0) // transparency row, handle it here for speed
|
|
||||||
{
|
|
||||||
for (size_t j=0; j<length; j++)
|
|
||||||
putPixelAt<bpp>(dest, destX + (rotate?(-j):(j)), destY, type, specialPalette);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
destX += rotate ? (-length) : (length);
|
|
||||||
totalRowLength += length;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCreatureAnimation::nextFrame(SDL_Surface *dest, bool attacker)
|
void CCreatureAnimation::nextFrame(SDL_Surface *dest, bool attacker)
|
||||||
{
|
{
|
||||||
// Note: please notice that attacker value is inversed when passed further.
|
size_t frame = floor(currentFrame);
|
||||||
// This is intended behavior because "attacker" actually does not needs rotation
|
|
||||||
switch(dest->format->BytesPerPixel)
|
IImage * image = nullptr;
|
||||||
{
|
|
||||||
case 2: return nextFrameT<2>(dest, !attacker);
|
if(attacker)
|
||||||
case 3: return nextFrameT<3>(dest, !attacker);
|
image = forward->getImage(frame, type);
|
||||||
case 4: return nextFrameT<4>(dest, !attacker);
|
else
|
||||||
default:
|
image = reverse->getImage(frame, type);
|
||||||
logGlobal->error("%d bpp is not supported!", (int)dest->format->BitsPerPixel);
|
|
||||||
}
|
IImage::BorderPallete borderPallete;
|
||||||
|
genBorderPalette(borderPallete);
|
||||||
|
|
||||||
|
image->setBorderPallete(borderPallete);
|
||||||
|
|
||||||
|
image->draw(dest, pos.x, pos.y);
|
||||||
}
|
}
|
||||||
|
|
||||||
int CCreatureAnimation::framesInGroup(CCreatureAnim::EAnimType group) const
|
int CCreatureAnimation::framesInGroup(CCreatureAnim::EAnimType group) const
|
||||||
{
|
{
|
||||||
if(dataOffsets.count(group) == 0)
|
return forward->size(group);
|
||||||
return 0;
|
|
||||||
|
|
||||||
return dataOffsets.at(group).size();
|
|
||||||
}
|
|
||||||
|
|
||||||
ui8 * CCreatureAnimation::getPixelAddr(SDL_Surface * dest, int X, int Y) const
|
|
||||||
{
|
|
||||||
return (ui8*)dest->pixels + X * dest->format->BytesPerPixel + Y * dest->pitch;
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int bpp>
|
|
||||||
inline void CCreatureAnimation::putPixelAt(SDL_Surface * dest, int X, int Y, size_t index, const std::array<SDL_Color, 8> & special) const
|
|
||||||
{
|
|
||||||
if ( X < pos.x + pos.w && Y < pos.y + pos.h && X >= 0 && Y >= 0)
|
|
||||||
putPixel<bpp>(getPixelAddr(dest, X, Y), palette[index], index, special);
|
|
||||||
}
|
|
||||||
|
|
||||||
template<int bpp>
|
|
||||||
inline void CCreatureAnimation::putPixel(ui8 * dest, const SDL_Color & color, size_t index, const std::array<SDL_Color, 8> & special) const
|
|
||||||
{
|
|
||||||
if((index <= 1) || (index >=4 && index < 8))
|
|
||||||
{
|
|
||||||
const SDL_Color & pal = special[index];
|
|
||||||
ColorPutter<bpp, 0>::PutColor(dest, pal.r, pal.g, pal.b, pal.a);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
ColorPutter<bpp, 0>::PutColor(dest, color.r, color.g, color.b);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool CCreatureAnimation::isDead() const
|
bool CCreatureAnimation::isDead() const
|
||||||
@@ -456,7 +328,8 @@ void CCreatureAnimation::pause()
|
|||||||
|
|
||||||
void CCreatureAnimation::play()
|
void CCreatureAnimation::play()
|
||||||
{
|
{
|
||||||
|
//logAnim->trace("Play %s group %d at %d:%d", name, static_cast<int>(getType()), pos.x, pos.y);
|
||||||
speed = 0;
|
speed = 0;
|
||||||
if (speedController(this, type) != 0)
|
if(speedController(this, type) != 0)
|
||||||
speed = 1 / speedController(this, type);
|
speed = 1 / speedController(this, type);
|
||||||
}
|
}
|
||||||
|
@@ -10,8 +10,8 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "../../lib/FunctionList.h"
|
#include "../../lib/FunctionList.h"
|
||||||
#include "../gui/SDL_Extensions.h"
|
|
||||||
#include "../widgets/Images.h"
|
#include "../widgets/Images.h"
|
||||||
|
#include "../gui/CAnimation.h"
|
||||||
|
|
||||||
class CIntObject;
|
class CIntObject;
|
||||||
class CCreatureAnimation;
|
class CCreatureAnimation;
|
||||||
@@ -52,21 +52,12 @@ public:
|
|||||||
typedef std::function<float(CCreatureAnimation *, size_t)> TSpeedController;
|
typedef std::function<float(CCreatureAnimation *, size_t)> TSpeedController;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
std::string defName;
|
std::string name;
|
||||||
|
std::shared_ptr<CAnimation> forward;
|
||||||
|
std::shared_ptr<CAnimation> reverse;
|
||||||
|
|
||||||
int fullWidth, fullHeight;
|
int fullWidth;
|
||||||
|
int fullHeight;
|
||||||
// palette, as read from def file
|
|
||||||
std::array<SDL_Color, 256> palette;
|
|
||||||
|
|
||||||
//key = id of group (note that some groups may be missing)
|
|
||||||
//value = offset of pixel data for each frame, vector size = number of frames in group
|
|
||||||
std::map<int, std::vector<unsigned int>> dataOffsets;
|
|
||||||
|
|
||||||
//animation raw data
|
|
||||||
//TODO: use vector instead?
|
|
||||||
std::unique_ptr<ui8[]> pixelData;
|
|
||||||
size_t pixelDataSize;
|
|
||||||
|
|
||||||
// speed of animation, measure in frames per second
|
// speed of animation, measure in frames per second
|
||||||
float speed;
|
float speed;
|
||||||
@@ -85,21 +76,10 @@ private:
|
|||||||
|
|
||||||
bool once; // animation will be played once and the reset to idling
|
bool once; // animation will be played once and the reset to idling
|
||||||
|
|
||||||
ui8 * getPixelAddr(SDL_Surface * dest, int ftcpX, int ftcpY) const;
|
|
||||||
|
|
||||||
template<int bpp>
|
|
||||||
void putPixelAt(SDL_Surface * dest, int X, int Y, size_t index, const std::array<SDL_Color, 8> & special) const;
|
|
||||||
|
|
||||||
template<int bpp>
|
|
||||||
void putPixel( ui8 * dest, const SDL_Color & color, size_t index, const std::array<SDL_Color, 8> & special) const;
|
|
||||||
|
|
||||||
template<int bpp>
|
|
||||||
void nextFrameT(SDL_Surface * dest, bool rotate);
|
|
||||||
|
|
||||||
void endAnimation();
|
void endAnimation();
|
||||||
|
|
||||||
/// creates 8 special colors for current frame
|
|
||||||
std::array<SDL_Color, 8> genSpecialPalette();
|
void genBorderPalette(IImage::BorderPallete & target);
|
||||||
public:
|
public:
|
||||||
|
|
||||||
// function(s) that will be called when animation ends, after reset to 1st frame
|
// function(s) that will be called when animation ends, after reset to 1st frame
|
||||||
@@ -113,12 +93,12 @@ public:
|
|||||||
/// name - path to .def file, relative to SPRITES/ directory
|
/// name - path to .def file, relative to SPRITES/ directory
|
||||||
/// controller - function that will return for how long *each* frame
|
/// controller - function that will return for how long *each* frame
|
||||||
/// in specified group of animation should be played, measured in seconds
|
/// in specified group of animation should be played, measured in seconds
|
||||||
CCreatureAnimation(std::string name, TSpeedController speedController);
|
CCreatureAnimation(const std::string & name_, TSpeedController speedController);
|
||||||
|
|
||||||
void setType(CCreatureAnim::EAnimType type); //sets type of animation and cleares framecount
|
void setType(CCreatureAnim::EAnimType type); //sets type of animation and cleares framecount
|
||||||
CCreatureAnim::EAnimType getType() const; //returns type of animation
|
CCreatureAnim::EAnimType getType() const; //returns type of animation
|
||||||
|
|
||||||
void nextFrame(SDL_Surface * dest, bool rotate);
|
void nextFrame(SDL_Surface * dest, bool attacker);
|
||||||
|
|
||||||
// should be called every frame, return true when animation was reset to beginning
|
// should be called every frame, return true when animation was reset to beginning
|
||||||
bool incrementFrame(float timePassed);
|
bool incrementFrame(float timePassed);
|
||||||
|
@@ -29,7 +29,7 @@ typedef std::map <size_t, std::vector <JsonNode> > source_map;
|
|||||||
typedef std::map<size_t, IImage* > image_map;
|
typedef std::map<size_t, IImage* > image_map;
|
||||||
typedef std::map<size_t, image_map > group_map;
|
typedef std::map<size_t, image_map > group_map;
|
||||||
|
|
||||||
/// Class for def loading, methods are based on CDefHandler
|
/// Class for def loading
|
||||||
/// After loading will store general info (palette and frame offsets) and pointer to file itself
|
/// After loading will store general info (palette and frame offsets) and pointer to file itself
|
||||||
class CDefFile
|
class CDefFile
|
||||||
{
|
{
|
||||||
@@ -100,6 +100,8 @@ public:
|
|||||||
|
|
||||||
void shiftPalette(int from, int howMany) override;
|
void shiftPalette(int from, int howMany) override;
|
||||||
|
|
||||||
|
void setBorderPallete(const BorderPallete & borderPallete) override;
|
||||||
|
|
||||||
friend class SDLImageLoader;
|
friend class SDLImageLoader;
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -157,6 +159,7 @@ public:
|
|||||||
void verticalFlip() override;
|
void verticalFlip() override;
|
||||||
|
|
||||||
void shiftPalette(int from, int howMany) override;
|
void shiftPalette(int from, int howMany) override;
|
||||||
|
void setBorderPallete(const BorderPallete & borderPallete) override;
|
||||||
|
|
||||||
friend class CompImageLoader;
|
friend class CompImageLoader;
|
||||||
};
|
};
|
||||||
@@ -985,6 +988,15 @@ void SDLImage::shiftPalette(int from, int howMany)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
|
||||||
|
{
|
||||||
|
if(surf->format->palette)
|
||||||
|
{
|
||||||
|
SDL_SetColors(surf, const_cast<SDL_Color *>(borderPallete.data()), 5, 3);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
SDLImage::~SDLImage()
|
SDLImage::~SDLImage()
|
||||||
{
|
{
|
||||||
SDL_FreeSurface(surf);
|
SDL_FreeSurface(surf);
|
||||||
@@ -1238,22 +1250,27 @@ CompImage::~CompImage()
|
|||||||
|
|
||||||
void CompImage::horizontalFlip()
|
void CompImage::horizontalFlip()
|
||||||
{
|
{
|
||||||
logAnim->error("CompImage::horizontalFlip is not implemented");
|
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompImage::verticalFlip()
|
void CompImage::verticalFlip()
|
||||||
{
|
{
|
||||||
logAnim->error("CompImage::verticalFlip is not implemented");
|
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompImage::shiftPalette(int from, int howMany)
|
void CompImage::shiftPalette(int from, int howMany)
|
||||||
{
|
{
|
||||||
logAnim->error("CompImage::shiftPalette is not implemented");
|
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CompImage::exportBitmap(const boost::filesystem::path& path) const
|
void CompImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
|
||||||
{
|
{
|
||||||
logAnim->error("CompImage::exportBitmap is not implemented");
|
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CompImage::exportBitmap(const boost::filesystem::path & path) const
|
||||||
|
{
|
||||||
|
logAnim->error("%s is not implemented", BOOST_CURRENT_FUNCTION);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@@ -1605,6 +1622,38 @@ size_t CAnimation::size(size_t group) const
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CAnimation::horizontalFlip()
|
||||||
|
{
|
||||||
|
for(auto & group : images)
|
||||||
|
for(auto & image : group.second)
|
||||||
|
image.second->horizontalFlip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAnimation::verticalFlip()
|
||||||
|
{
|
||||||
|
for(auto & group : images)
|
||||||
|
for(auto & image : group.second)
|
||||||
|
image.second->verticalFlip();
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAnimation::playerColored(PlayerColor player)
|
||||||
|
{
|
||||||
|
for(auto & group : images)
|
||||||
|
for(auto & image : group.second)
|
||||||
|
image.second->playerColored(player);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CAnimation::createFlippedGroup(const size_t sourceGroup, const size_t targetGroup)
|
||||||
|
{
|
||||||
|
for(size_t frame = 0; frame < size(sourceGroup); ++frame)
|
||||||
|
{
|
||||||
|
duplicateImage(sourceGroup, frame, targetGroup);
|
||||||
|
|
||||||
|
IImage * image = getImage(frame, targetGroup);
|
||||||
|
image->verticalFlip();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
float CFadeAnimation::initialCounter() const
|
float CFadeAnimation::initialCounter() const
|
||||||
{
|
{
|
||||||
if (fadingMode == EMode::OUT)
|
if (fadingMode == EMode::OUT)
|
||||||
|
@@ -24,6 +24,7 @@ class IImage
|
|||||||
{
|
{
|
||||||
int refCount;
|
int refCount;
|
||||||
public:
|
public:
|
||||||
|
using BorderPallete = std::array<SDL_Color, 3>;
|
||||||
|
|
||||||
//draws image on surface "where" at position
|
//draws image on surface "where" at position
|
||||||
virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, Rect * src = nullptr, ui8 alpha = 255) const=0;
|
virtual void draw(SDL_Surface * where, int posX = 0, int posY = 0, Rect * src = nullptr, ui8 alpha = 255) const=0;
|
||||||
@@ -49,6 +50,9 @@ public:
|
|||||||
//only indexed bitmaps, 16 colors maximum
|
//only indexed bitmaps, 16 colors maximum
|
||||||
virtual void shiftPalette(int from, int howMany) = 0;
|
virtual void shiftPalette(int from, int howMany) = 0;
|
||||||
|
|
||||||
|
//only indexed bitmaps, colors 5,6,7 must be special
|
||||||
|
virtual void setBorderPallete(const BorderPallete & borderPallete) = 0;
|
||||||
|
|
||||||
virtual void horizontalFlip() = 0;
|
virtual void horizontalFlip() = 0;
|
||||||
virtual void verticalFlip() = 0;
|
virtual void verticalFlip() = 0;
|
||||||
|
|
||||||
@@ -127,6 +131,12 @@ public:
|
|||||||
|
|
||||||
//total count of frames in group (including not loaded)
|
//total count of frames in group (including not loaded)
|
||||||
size_t size(size_t group=0) const;
|
size_t size(size_t group=0) const;
|
||||||
|
|
||||||
|
void horizontalFlip();
|
||||||
|
void verticalFlip();
|
||||||
|
void playerColored(PlayerColor player);
|
||||||
|
|
||||||
|
void createFlippedGroup(const size_t sourceGroup, const size_t targetGroup);
|
||||||
};
|
};
|
||||||
|
|
||||||
const float DEFAULT_DELTA = 0.05f;
|
const float DEFAULT_DELTA = 0.05f;
|
||||||
|
@@ -23,11 +23,20 @@ void CCursorHandler::initCursor()
|
|||||||
xpos = ypos = 0;
|
xpos = ypos = 0;
|
||||||
type = ECursor::DEFAULT;
|
type = ECursor::DEFAULT;
|
||||||
dndObject = nullptr;
|
dndObject = nullptr;
|
||||||
currentCursor = nullptr;
|
|
||||||
|
cursors =
|
||||||
|
{
|
||||||
|
make_unique<CAnimImage>("CRADVNTR", 0),
|
||||||
|
make_unique<CAnimImage>("CRCOMBAT", 0),
|
||||||
|
make_unique<CAnimImage>("CRDEFLT", 0),
|
||||||
|
make_unique<CAnimImage>("CRSPELL", 0)
|
||||||
|
};
|
||||||
|
|
||||||
|
currentCursor = cursors.at(int(ECursor::DEFAULT)).get();
|
||||||
|
|
||||||
help = CSDL_Ext::newSurface(40,40);
|
help = CSDL_Ext::newSurface(40,40);
|
||||||
//No blending. Ensure, that we are copying pixels during "screen restore draw"
|
//No blending. Ensure, that we are copying pixels during "screen restore draw"
|
||||||
SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
|
SDL_SetSurfaceBlendMode(help,SDL_BLENDMODE_NONE);
|
||||||
SDL_ShowCursor(SDL_DISABLE);
|
SDL_ShowCursor(SDL_DISABLE);
|
||||||
|
|
||||||
changeGraphic(ECursor::ADVENTURE, 0);
|
changeGraphic(ECursor::ADVENTURE, 0);
|
||||||
@@ -35,32 +44,23 @@ void CCursorHandler::initCursor()
|
|||||||
|
|
||||||
void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index)
|
void CCursorHandler::changeGraphic(ECursor::ECursorTypes type, int index)
|
||||||
{
|
{
|
||||||
std::string cursorDefs[4] = { "CRADVNTR.DEF", "CRCOMBAT.DEF", "CRDEFLT.DEF", "CRSPELL.DEF" };
|
if(type != this->type)
|
||||||
|
|
||||||
if (type != this->type)
|
|
||||||
{
|
{
|
||||||
BLOCK_CAPTURING; // not used here
|
|
||||||
|
|
||||||
this->type = type;
|
this->type = type;
|
||||||
this->frame = index;
|
this->frame = index;
|
||||||
|
currentCursor = cursors.at(int(type)).get();
|
||||||
delete currentCursor;
|
currentCursor->setFrame(index);
|
||||||
currentCursor = new CAnimImage(cursorDefs[int(type)], index);
|
|
||||||
}
|
}
|
||||||
|
else if(index != this->frame)
|
||||||
if (frame != index)
|
|
||||||
{
|
{
|
||||||
frame = index;
|
this->frame = index;
|
||||||
currentCursor->setFrame(index);
|
currentCursor->setFrame(index);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCursorHandler::dragAndDropCursor(CAnimImage * object)
|
void CCursorHandler::dragAndDropCursor(std::unique_ptr<CAnimImage> object)
|
||||||
{
|
{
|
||||||
if (dndObject)
|
dndObject = std::move(object);
|
||||||
delete dndObject;
|
|
||||||
|
|
||||||
dndObject = object;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCursorHandler::cursorMove(const int & x, const int & y)
|
void CCursorHandler::cursorMove(const int & x, const int & y)
|
||||||
@@ -101,13 +101,6 @@ void CCursorHandler::drawRestored()
|
|||||||
|
|
||||||
SDL_Rect temp_rect = genRect(40, 40, x, y);
|
SDL_Rect temp_rect = genRect(40, 40, x, y);
|
||||||
SDL_BlitSurface(help, nullptr, screen, &temp_rect);
|
SDL_BlitSurface(help, nullptr, screen, &temp_rect);
|
||||||
//blitAt(help,x,y);
|
|
||||||
}
|
|
||||||
|
|
||||||
void CCursorHandler::draw(SDL_Surface *to)
|
|
||||||
{
|
|
||||||
currentCursor->moveTo(Point(xpos, ypos));
|
|
||||||
currentCursor->showAll(screen);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CCursorHandler::shiftPos( int &x, int &y )
|
void CCursorHandler::shiftPos( int &x, int &y )
|
||||||
@@ -233,12 +226,10 @@ void CCursorHandler::render()
|
|||||||
drawRestored();
|
drawRestored();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
CCursorHandler::CCursorHandler() = default;
|
||||||
|
|
||||||
CCursorHandler::~CCursorHandler()
|
CCursorHandler::~CCursorHandler()
|
||||||
{
|
{
|
||||||
if(help)
|
if(help)
|
||||||
SDL_FreeSurface(help);
|
SDL_FreeSurface(help);
|
||||||
|
|
||||||
delete currentCursor;
|
|
||||||
delete dndObject;
|
|
||||||
}
|
}
|
||||||
|
@@ -17,27 +17,28 @@ namespace ECursor
|
|||||||
enum ECursorTypes { ADVENTURE, COMBAT, DEFAULT, SPELLBOOK };
|
enum ECursorTypes { ADVENTURE, COMBAT, DEFAULT, SPELLBOOK };
|
||||||
|
|
||||||
enum EBattleCursors { COMBAT_BLOCKED, COMBAT_MOVE, COMBAT_FLY, COMBAT_SHOOT,
|
enum EBattleCursors { COMBAT_BLOCKED, COMBAT_MOVE, COMBAT_FLY, COMBAT_SHOOT,
|
||||||
COMBAT_HERO, COMBAT_QUERY, COMBAT_POINTER,
|
COMBAT_HERO, COMBAT_QUERY, COMBAT_POINTER,
|
||||||
//various attack frames
|
//various attack frames
|
||||||
COMBAT_SHOOT_PENALTY = 15, COMBAT_SHOOT_CATAPULT, COMBAT_HEAL,
|
COMBAT_SHOOT_PENALTY = 15, COMBAT_SHOOT_CATAPULT, COMBAT_HEAL,
|
||||||
COMBAT_SACRIFICE, COMBAT_TELEPORT};
|
COMBAT_SACRIFICE, COMBAT_TELEPORT};
|
||||||
}
|
}
|
||||||
|
|
||||||
/// handles mouse cursor
|
/// handles mouse cursor
|
||||||
class CCursorHandler
|
class CCursorHandler final
|
||||||
{
|
{
|
||||||
SDL_Surface * help;
|
SDL_Surface * help;
|
||||||
CAnimImage * currentCursor;
|
CAnimImage * currentCursor;
|
||||||
CAnimImage * dndObject; //if set, overrides currentCursor
|
|
||||||
|
std::unique_ptr<CAnimImage> dndObject; //if set, overrides currentCursor
|
||||||
|
|
||||||
|
std::array<std::unique_ptr<CAnimImage>, 4> cursors;
|
||||||
|
|
||||||
bool showing;
|
bool showing;
|
||||||
|
|
||||||
/// Draw cursor preserving original image below cursor
|
/// Draw cursor preserving original image below cursor
|
||||||
void drawWithScreenRestore();
|
void drawWithScreenRestore();
|
||||||
/// Restore original image below cursor
|
/// Restore original image below cursor
|
||||||
void drawRestored();
|
void drawRestored();
|
||||||
/// Simple draw cursor
|
|
||||||
void draw(SDL_Surface *to);
|
|
||||||
|
|
||||||
public:
|
public:
|
||||||
/// position of cursor
|
/// position of cursor
|
||||||
int xpos, ypos;
|
int xpos, ypos;
|
||||||
@@ -58,8 +59,8 @@ public:
|
|||||||
* @param image Image to replace cursor with or nullptr to use the normal
|
* @param image Image to replace cursor with or nullptr to use the normal
|
||||||
* cursor. CursorHandler takes ownership of object
|
* cursor. CursorHandler takes ownership of object
|
||||||
*/
|
*/
|
||||||
void dragAndDropCursor (CAnimImage * image);
|
void dragAndDropCursor (std::unique_ptr<CAnimImage> image);
|
||||||
|
|
||||||
void render();
|
void render();
|
||||||
|
|
||||||
void shiftPos( int &x, int &y );
|
void shiftPos( int &x, int &y );
|
||||||
@@ -71,5 +72,6 @@ public:
|
|||||||
/// Move cursor to screen center
|
/// Move cursor to screen center
|
||||||
void centerCursor();
|
void centerCursor();
|
||||||
|
|
||||||
|
CCursorHandler();
|
||||||
~CCursorHandler();
|
~CCursorHandler();
|
||||||
};
|
};
|
||||||
|
@@ -459,8 +459,7 @@ void CGuiHandler::renderFrame()
|
|||||||
// draw the mouse cursor and update the screen
|
// draw the mouse cursor and update the screen
|
||||||
CCS->curh->render();
|
CCS->curh->render();
|
||||||
|
|
||||||
if(0 != SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr))
|
SDL_RenderCopy(mainRenderer, screenTexture, nullptr, nullptr);
|
||||||
logGlobal->error("%s SDL_RenderCopy %s", __FUNCTION__, SDL_GetError());
|
|
||||||
|
|
||||||
SDL_RenderPresent(mainRenderer);
|
SDL_RenderPresent(mainRenderer);
|
||||||
}
|
}
|
||||||
|
@@ -290,7 +290,7 @@ void CHeroArtPlace::select ()
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
CCS->curh->dragAndDropCursor(new CAnimImage("artifact", ourArt->artType->iconIndex));
|
CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", ourArt->artType->iconIndex));
|
||||||
ourOwner->commonInfo->src.setTo(this, false);
|
ourOwner->commonInfo->src.setTo(this, false);
|
||||||
ourOwner->markPossibleSlots(ourArt);
|
ourOwner->markPossibleSlots(ourArt);
|
||||||
|
|
||||||
@@ -766,7 +766,7 @@ void CArtifactsOfHero::artifactMoved(const ArtifactLocation &src, const Artifact
|
|||||||
commonInfo->src.art = dst.getArt();
|
commonInfo->src.art = dst.getArt();
|
||||||
commonInfo->src.slotID = dst.slot;
|
commonInfo->src.slotID = dst.slot;
|
||||||
assert(commonInfo->src.AOH);
|
assert(commonInfo->src.AOH);
|
||||||
CCS->curh->dragAndDropCursor(new CAnimImage("artifact", dst.getArt()->artType->iconIndex));
|
CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", dst.getArt()->artType->iconIndex));
|
||||||
markPossibleSlots(dst.getArt());
|
markPossibleSlots(dst.getArt());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@@ -24,6 +24,7 @@
|
|||||||
|
|
||||||
#include "../gui/SDL_Extensions.h"
|
#include "../gui/SDL_Extensions.h"
|
||||||
#include "../gui/CGuiHandler.h"
|
#include "../gui/CGuiHandler.h"
|
||||||
|
#include "../gui/CAnimation.h"
|
||||||
#include "../widgets/MiscWidgets.h"
|
#include "../widgets/MiscWidgets.h"
|
||||||
#include "../widgets/CComponent.h"
|
#include "../widgets/CComponent.h"
|
||||||
|
|
||||||
@@ -107,7 +108,7 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
|
|||||||
quitButton = new CButton(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [&](){ close(); }, SDLK_RETURN);
|
quitButton = new CButton(Point(609, 516), "hsbtns.def", CButton::tooltip(heroscrn[17]), [&](){ close(); }, SDLK_RETURN);
|
||||||
quitButton->assignedKeys.insert(SDLK_ESCAPE);
|
quitButton->assignedKeys.insert(SDLK_ESCAPE);
|
||||||
dismissButton = new CButton(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [&](){ dismissCurrent(); }, SDLK_d);
|
dismissButton = new CButton(Point(454, 429), "hsbtns2.def", CButton::tooltip(heroscrn[28]), [&](){ dismissCurrent(); }, SDLK_d);
|
||||||
questlogButton = new CButton(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [&](){ questlog(); }, SDLK_q);
|
questlogButton = new CButton(Point(314, 429), "hsbtns4.def", CButton::tooltip(heroscrn[0]), [=](){ LOCPLINT->showQuestLog(); }, SDLK_q);
|
||||||
|
|
||||||
formations = new CToggleGroup(0);
|
formations = new CToggleGroup(0);
|
||||||
formations->addToggle(0, new CToggleButton(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t));
|
formations->addToggle(0, new CToggleButton(Point(481, 483), "hsbtns6.def", std::make_pair(heroscrn[23], heroscrn[29]), 0, SDLK_t));
|
||||||
@@ -144,11 +145,12 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
|
|||||||
luck = new MoraleLuckBox(false, Rect(233,179,53,45));
|
luck = new MoraleLuckBox(false, Rect(233,179,53,45));
|
||||||
spellPointsArea = new LRClickableAreaWText(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]);
|
spellPointsArea = new LRClickableAreaWText(Rect(162,228, 136, 42), CGI->generaltexth->heroscrn[22]);
|
||||||
|
|
||||||
|
auto secSkills = std::make_shared<CAnimation>("SECSKILL");
|
||||||
for(int i = 0; i < std::min<size_t>(hero->secSkills.size(), 8u); ++i)
|
for(int i = 0; i < std::min<size_t>(hero->secSkills.size(), 8u); ++i)
|
||||||
{
|
{
|
||||||
Rect r = Rect(i%2 == 0 ? 18 : 162, 276 + 48 * (i/2), 136, 42);
|
Rect r = Rect(i%2 == 0 ? 18 : 162, 276 + 48 * (i/2), 136, 42);
|
||||||
secSkillAreas.push_back(new LRClickableAreaWTextComp(r, CComponent::secskill));
|
secSkillAreas.push_back(new LRClickableAreaWTextComp(r, CComponent::secskill));
|
||||||
secSkillImages.push_back(new CAnimImage("SECSKILL", 0, 0, r.x, r.y));
|
secSkillImages.push_back(new CAnimImage(secSkills, 0, 0, r.x, r.y));
|
||||||
}
|
}
|
||||||
|
|
||||||
//dismiss / quest log
|
//dismiss / quest log
|
||||||
@@ -158,12 +160,14 @@ CHeroWindow::CHeroWindow(const CGHeroInstance *hero):
|
|||||||
//////////////////////////////////////////////////////////////////////////???????????????
|
//////////////////////////////////////////////////////////////////////////???????????????
|
||||||
|
|
||||||
//primary skills & exp and mana
|
//primary skills & exp and mana
|
||||||
new CAnimImage("PSKIL42", 0, 0, 32, 111, false);
|
auto primSkills = std::make_shared<CAnimation>("PSKIL42");
|
||||||
new CAnimImage("PSKIL42", 1, 0, 102, 111, false);
|
primSkills->preload();
|
||||||
new CAnimImage("PSKIL42", 2, 0, 172, 111, false);
|
new CAnimImage(primSkills, 0, 0, 32, 111);
|
||||||
new CAnimImage("PSKIL42", 3, 0, 162, 230, false);
|
new CAnimImage(primSkills, 1, 0, 102, 111);
|
||||||
new CAnimImage("PSKIL42", 4, 0, 20, 230, false);
|
new CAnimImage(primSkills, 2, 0, 172, 111);
|
||||||
new CAnimImage("PSKIL42", 5, 0, 242, 111, false);
|
new CAnimImage(primSkills, 3, 0, 162, 230);
|
||||||
|
new CAnimImage(primSkills, 4, 0, 20, 230);
|
||||||
|
new CAnimImage(primSkills, 5, 0, 242, 111);
|
||||||
|
|
||||||
// various texts
|
// various texts
|
||||||
new CLabel( 52, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[1]);
|
new CLabel( 52, 99, FONT_SMALL, CENTER, Colors::YELLOW, CGI->generaltexth->jktexts[1]);
|
||||||
@@ -306,11 +310,6 @@ void CHeroWindow::dismissCurrent()
|
|||||||
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, 0, false);
|
LOCPLINT->showYesNoDialog(CGI->generaltexth->allTexts[22], ony, 0, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
void CHeroWindow::questlog()
|
|
||||||
{
|
|
||||||
LOCPLINT->showQuestLog();
|
|
||||||
}
|
|
||||||
|
|
||||||
void CHeroWindow::commanderWindow()
|
void CHeroWindow::commanderWindow()
|
||||||
{
|
{
|
||||||
//TODO: allow equipping commander artifacts by drag / drop
|
//TODO: allow equipping commander artifacts by drag / drop
|
||||||
|
@@ -86,7 +86,6 @@ public:
|
|||||||
void showAll(SDL_Surface * to) override;
|
void showAll(SDL_Surface * to) override;
|
||||||
|
|
||||||
void dismissCurrent(); //dissmissed currently displayed hero (curHero)
|
void dismissCurrent(); //dissmissed currently displayed hero (curHero)
|
||||||
void questlog(); //show quest log in hero window
|
|
||||||
void commanderWindow();
|
void commanderWindow();
|
||||||
void switchHero(); //changes displayed hero
|
void switchHero(); //changes displayed hero
|
||||||
virtual void updateGarrisons() override; //updates the morale widget and calls the parent
|
virtual void updateGarrisons() override; //updates the morale widget and calls the parent
|
||||||
|
@@ -187,7 +187,7 @@ void CTradeWindow::CTradeableItem::clickLeft(tribool down, bool previousState)
|
|||||||
aw->arts->markPossibleSlots(art);
|
aw->arts->markPossibleSlots(art);
|
||||||
|
|
||||||
//aw->arts->commonInfo->dst.AOH = aw->arts;
|
//aw->arts->commonInfo->dst.AOH = aw->arts;
|
||||||
CCS->curh->dragAndDropCursor(new CAnimImage("artifact", art->artType->iconIndex));
|
CCS->curh->dragAndDropCursor(make_unique<CAnimImage>("artifact", art->artType->iconIndex));
|
||||||
|
|
||||||
aw->arts->artifactsOnAltar.erase(art);
|
aw->arts->artifactsOnAltar.erase(art);
|
||||||
setID(-1);
|
setID(-1);
|
||||||
|
@@ -37,7 +37,6 @@ class CGObjectInstance;
|
|||||||
class CCreature;
|
class CCreature;
|
||||||
class CMap;
|
class CMap;
|
||||||
struct StartInfo;
|
struct StartInfo;
|
||||||
struct SDL_Surface;
|
|
||||||
class CMapHandler;
|
class CMapHandler;
|
||||||
struct SetObjectProperty;
|
struct SetObjectProperty;
|
||||||
struct MetaString;
|
struct MetaString;
|
||||||
|
Reference in New Issue
Block a user