mirror of
https://github.com/vcmi/vcmi.git
synced 2025-07-15 01:24:45 +02:00
Merge pull request #625 from Toneyisnow/toneyisnow/Battle_Clone_Effect
Implement the Clone Effect in battle.
This commit is contained in:
@ -739,6 +739,12 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units
|
|||||||
if(unit->alive() && animation->isDead())
|
if(unit->alive() && animation->isDead())
|
||||||
animation->setType(CCreatureAnim::HOLDING);
|
animation->setType(CCreatureAnim::HOLDING);
|
||||||
|
|
||||||
|
if (unit->isClone())
|
||||||
|
{
|
||||||
|
std::unique_ptr<ColorShifterDeepBlue> shifter(new ColorShifterDeepBlue());
|
||||||
|
animation->shiftColor(shifter.get());
|
||||||
|
}
|
||||||
|
|
||||||
//TODO: handle more cases
|
//TODO: handle more cases
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
@ -90,6 +90,12 @@ CBattleStackAnimation::CBattleStackAnimation(CBattleInterface * owner, const CSt
|
|||||||
assert(myAnim);
|
assert(myAnim);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CBattleStackAnimation::shiftColor(const ColorShifter * shifter)
|
||||||
|
{
|
||||||
|
assert(myAnim);
|
||||||
|
myAnim->shiftColor(shifter);
|
||||||
|
}
|
||||||
|
|
||||||
void CAttackAnimation::nextFrame()
|
void CAttackAnimation::nextFrame()
|
||||||
{
|
{
|
||||||
if(myAnim->getType() != group)
|
if(myAnim->getType() != group)
|
||||||
|
@ -43,6 +43,8 @@ public:
|
|||||||
const CStack * stack; //id of stack whose animation it is
|
const CStack * stack; //id of stack whose animation it is
|
||||||
|
|
||||||
CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);
|
CBattleStackAnimation(CBattleInterface * _owner, const CStack * _stack);
|
||||||
|
|
||||||
|
void shiftColor(const ColorShifter * shifter);
|
||||||
};
|
};
|
||||||
|
|
||||||
/// This class is responsible for managing the battle attack animation
|
/// This class is responsible for managing the battle attack animation
|
||||||
|
@ -142,6 +142,15 @@ void CCreatureAnimation::setType(CCreatureAnim::EAnimType type)
|
|||||||
play();
|
play();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CCreatureAnimation::shiftColor(const ColorShifter* shifter)
|
||||||
|
{
|
||||||
|
if(forward)
|
||||||
|
forward->shiftColor(shifter);
|
||||||
|
|
||||||
|
if(reverse)
|
||||||
|
reverse->shiftColor(shifter);
|
||||||
|
}
|
||||||
|
|
||||||
CCreatureAnimation::CCreatureAnimation(const std::string & name_, TSpeedController controller)
|
CCreatureAnimation::CCreatureAnimation(const std::string & name_, TSpeedController controller)
|
||||||
: name(name_),
|
: name(name_),
|
||||||
speed(0.1),
|
speed(0.1),
|
||||||
|
@ -104,6 +104,9 @@ public:
|
|||||||
bool incrementFrame(float timePassed);
|
bool incrementFrame(float timePassed);
|
||||||
void setBorderColor(SDL_Color palette);
|
void setBorderColor(SDL_Color palette);
|
||||||
|
|
||||||
|
// tint color effect
|
||||||
|
void shiftColor(const ColorShifter * shifter);
|
||||||
|
|
||||||
float getCurrentFrame() const; // Gets the current frame ID relative to frame group.
|
float getCurrentFrame() const; // Gets the current frame ID relative to frame group.
|
||||||
|
|
||||||
void playOnce(CCreatureAnim::EAnimType type); //plays once given stage of animation, then resets to 2
|
void playOnce(CCreatureAnim::EAnimType type); //plays once given stage of animation, then resets to 2
|
||||||
|
@ -69,6 +69,9 @@ public:
|
|||||||
class SDLImage : public IImage
|
class SDLImage : public IImage
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
|
const static int DEFAULT_PALETTE_COLORS = 256;
|
||||||
|
|
||||||
//Surface without empty borders
|
//Surface without empty borders
|
||||||
SDL_Surface * surf;
|
SDL_Surface * surf;
|
||||||
//size of left and top borders
|
//size of left and top borders
|
||||||
@ -87,6 +90,9 @@ public:
|
|||||||
SDLImage(SDL_Surface * from, bool extraRef);
|
SDLImage(SDL_Surface * from, bool extraRef);
|
||||||
~SDLImage();
|
~SDLImage();
|
||||||
|
|
||||||
|
// Keep the original palette, in order to do color switching operation
|
||||||
|
void savePalette();
|
||||||
|
|
||||||
void draw(SDL_Surface * where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
void draw(SDL_Surface * where, int posX=0, int posY=0, Rect *src=nullptr, ui8 alpha=255) const override;
|
||||||
void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override;
|
void draw(SDL_Surface * where, SDL_Rect * dest, SDL_Rect * src, ui8 alpha=255) const override;
|
||||||
std::shared_ptr<IImage> scaleFast(float scale) const override;
|
std::shared_ptr<IImage> scaleFast(float scale) const override;
|
||||||
@ -100,10 +106,15 @@ public:
|
|||||||
void verticalFlip() override;
|
void verticalFlip() override;
|
||||||
|
|
||||||
void shiftPalette(int from, int howMany) override;
|
void shiftPalette(int from, int howMany) override;
|
||||||
|
void adjustPalette(const ColorShifter * shifter) override;
|
||||||
|
void resetPalette() override;
|
||||||
|
|
||||||
void setBorderPallete(const BorderPallete & borderPallete) override;
|
void setBorderPallete(const BorderPallete & borderPallete) override;
|
||||||
|
|
||||||
friend class SDLImageLoader;
|
friend class SDLImageLoader;
|
||||||
|
|
||||||
|
private:
|
||||||
|
SDL_Palette * originalPalette;
|
||||||
};
|
};
|
||||||
|
|
||||||
class SDLImageLoader
|
class SDLImageLoader
|
||||||
@ -497,8 +508,8 @@ void SDLImageLoader::init(Point SpriteSize, Point Margins, Point FullSize, SDL_C
|
|||||||
image->fullSize = FullSize;
|
image->fullSize = FullSize;
|
||||||
|
|
||||||
//Prepare surface
|
//Prepare surface
|
||||||
SDL_Palette * p = SDL_AllocPalette(256);
|
SDL_Palette * p = SDL_AllocPalette(SDLImage::DEFAULT_PALETTE_COLORS);
|
||||||
SDL_SetPaletteColors(p, pal, 0, 256);
|
SDL_SetPaletteColors(p, pal, 0, SDLImage::DEFAULT_PALETTE_COLORS);
|
||||||
SDL_SetSurfacePalette(image->surf, p);
|
SDL_SetSurfacePalette(image->surf, p);
|
||||||
SDL_FreePalette(p);
|
SDL_FreePalette(p);
|
||||||
|
|
||||||
@ -548,18 +559,27 @@ IImage::~IImage() = default;
|
|||||||
SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group)
|
SDLImage::SDLImage(CDefFile * data, size_t frame, size_t group)
|
||||||
: surf(nullptr),
|
: surf(nullptr),
|
||||||
margins(0, 0),
|
margins(0, 0),
|
||||||
fullSize(0, 0)
|
fullSize(0, 0),
|
||||||
|
originalPalette(nullptr)
|
||||||
{
|
{
|
||||||
SDLImageLoader loader(this);
|
SDLImageLoader loader(this);
|
||||||
data->loadFrame(frame, group, loader);
|
data->loadFrame(frame, group, loader);
|
||||||
|
|
||||||
|
savePalette();
|
||||||
}
|
}
|
||||||
|
|
||||||
SDLImage::SDLImage(SDL_Surface * from, bool extraRef)
|
SDLImage::SDLImage(SDL_Surface * from, bool extraRef)
|
||||||
: surf(nullptr),
|
: surf(nullptr),
|
||||||
margins(0, 0),
|
margins(0, 0),
|
||||||
fullSize(0, 0)
|
fullSize(0, 0),
|
||||||
|
originalPalette(nullptr)
|
||||||
{
|
{
|
||||||
surf = from;
|
surf = from;
|
||||||
|
if (surf == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
savePalette();
|
||||||
|
|
||||||
if (extraRef)
|
if (extraRef)
|
||||||
surf->refcount++;
|
surf->refcount++;
|
||||||
fullSize.x = surf->w;
|
fullSize.x = surf->w;
|
||||||
@ -569,7 +589,8 @@ SDLImage::SDLImage(SDL_Surface * from, bool extraRef)
|
|||||||
SDLImage::SDLImage(const JsonNode & conf)
|
SDLImage::SDLImage(const JsonNode & conf)
|
||||||
: surf(nullptr),
|
: surf(nullptr),
|
||||||
margins(0, 0),
|
margins(0, 0),
|
||||||
fullSize(0, 0)
|
fullSize(0, 0),
|
||||||
|
originalPalette(nullptr)
|
||||||
{
|
{
|
||||||
std::string filename = conf["file"].String();
|
std::string filename = conf["file"].String();
|
||||||
|
|
||||||
@ -578,6 +599,8 @@ SDLImage::SDLImage(const JsonNode & conf)
|
|||||||
if(surf == nullptr)
|
if(surf == nullptr)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
savePalette();
|
||||||
|
|
||||||
const JsonNode & jsonMargins = conf["margins"];
|
const JsonNode & jsonMargins = conf["margins"];
|
||||||
|
|
||||||
margins.x = jsonMargins["left"].Integer();
|
margins.x = jsonMargins["left"].Integer();
|
||||||
@ -600,7 +623,8 @@ SDLImage::SDLImage(const JsonNode & conf)
|
|||||||
SDLImage::SDLImage(std::string filename)
|
SDLImage::SDLImage(std::string filename)
|
||||||
: surf(nullptr),
|
: surf(nullptr),
|
||||||
margins(0, 0),
|
margins(0, 0),
|
||||||
fullSize(0, 0)
|
fullSize(0, 0),
|
||||||
|
originalPalette(nullptr)
|
||||||
{
|
{
|
||||||
surf = BitmapHandler::loadBitmap(filename);
|
surf = BitmapHandler::loadBitmap(filename);
|
||||||
|
|
||||||
@ -611,6 +635,7 @@ SDLImage::SDLImage(std::string filename)
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
savePalette();
|
||||||
fullSize.x = surf->w;
|
fullSize.x = surf->w;
|
||||||
fullSize.y = surf->h;
|
fullSize.y = surf->h;
|
||||||
}
|
}
|
||||||
@ -736,6 +761,19 @@ void SDLImage::verticalFlip()
|
|||||||
surf = flipped;
|
surf = flipped;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Keep the original palette, in order to do color switching operation
|
||||||
|
void SDLImage::savePalette()
|
||||||
|
{
|
||||||
|
// For some images that don't have palette, skip this
|
||||||
|
if(surf->format->palette == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
if(originalPalette == nullptr)
|
||||||
|
originalPalette = SDL_AllocPalette(DEFAULT_PALETTE_COLORS);
|
||||||
|
|
||||||
|
SDL_SetPaletteColors(originalPalette, surf->format->palette->colors, 0, DEFAULT_PALETTE_COLORS);
|
||||||
|
}
|
||||||
|
|
||||||
void SDLImage::shiftPalette(int from, int howMany)
|
void SDLImage::shiftPalette(int from, int howMany)
|
||||||
{
|
{
|
||||||
//works with at most 16 colors, if needed more -> increase values
|
//works with at most 16 colors, if needed more -> increase values
|
||||||
@ -753,6 +791,29 @@ void SDLImage::shiftPalette(int from, int howMany)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void SDLImage::adjustPalette(const ColorShifter * shifter)
|
||||||
|
{
|
||||||
|
if(originalPalette == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
SDL_Palette* palette = surf->format->palette;
|
||||||
|
|
||||||
|
// Note: here we skip the first 8 colors in the palette that predefined in H3Palette
|
||||||
|
for(int i = 8; i < palette->ncolors; i++)
|
||||||
|
{
|
||||||
|
palette->colors[i] = shifter->shiftColor(originalPalette->colors[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void SDLImage::resetPalette()
|
||||||
|
{
|
||||||
|
if(originalPalette == nullptr)
|
||||||
|
return;
|
||||||
|
|
||||||
|
// Always keept the original palette not changed, copy a new palette to assign to surface
|
||||||
|
SDL_SetPaletteColors(surf->format->palette, originalPalette->colors, 0, originalPalette->ncolors);
|
||||||
|
}
|
||||||
|
|
||||||
void SDLImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
|
void SDLImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
|
||||||
{
|
{
|
||||||
if(surf->format->palette)
|
if(surf->format->palette)
|
||||||
@ -764,6 +825,12 @@ void SDLImage::setBorderPallete(const IImage::BorderPallete & borderPallete)
|
|||||||
SDLImage::~SDLImage()
|
SDLImage::~SDLImage()
|
||||||
{
|
{
|
||||||
SDL_FreeSurface(surf);
|
SDL_FreeSurface(surf);
|
||||||
|
|
||||||
|
if(originalPalette != nullptr)
|
||||||
|
{
|
||||||
|
SDL_FreePalette(originalPalette);
|
||||||
|
originalPalette = nullptr;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename)
|
std::shared_ptr<IImage> CAnimation::getFromExtraDef(std::string filename)
|
||||||
@ -1014,6 +1081,18 @@ void CAnimation::duplicateImage(const size_t sourceGroup, const size_t sourceFra
|
|||||||
load(index, targetGroup);
|
load(index, targetGroup);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CAnimation::shiftColor(const ColorShifter * shifter)
|
||||||
|
{
|
||||||
|
for(auto groupIter = images.begin(); groupIter != images.end(); groupIter++)
|
||||||
|
{
|
||||||
|
for(auto frameIter = groupIter->second.begin(); frameIter != groupIter->second.end(); frameIter++)
|
||||||
|
{
|
||||||
|
std::shared_ptr<IImage> image = frameIter->second;
|
||||||
|
image->adjustPalette(shifter);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void CAnimation::setCustom(std::string filename, size_t frame, size_t group)
|
void CAnimation::setCustom(std::string filename, size_t frame, size_t group)
|
||||||
{
|
{
|
||||||
if (source[group].size() <= frame)
|
if (source[group].size() <= frame)
|
||||||
|
@ -16,6 +16,7 @@
|
|||||||
struct SDL_Surface;
|
struct SDL_Surface;
|
||||||
class JsonNode;
|
class JsonNode;
|
||||||
class CDefFile;
|
class CDefFile;
|
||||||
|
class ColorShifter;
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Base class for images, can be used for non-animation pictures as well
|
* Base class for images, can be used for non-animation pictures as well
|
||||||
@ -44,6 +45,8 @@ 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;
|
||||||
|
virtual void adjustPalette(const ColorShifter * shifter) = 0;
|
||||||
|
virtual void resetPalette() = 0;
|
||||||
|
|
||||||
//only indexed bitmaps, colors 5,6,7 must be special
|
//only indexed bitmaps, colors 5,6,7 must be special
|
||||||
virtual void setBorderPallete(const BorderPallete & borderPallete) = 0;
|
virtual void setBorderPallete(const BorderPallete & borderPallete) = 0;
|
||||||
@ -98,6 +101,9 @@ public:
|
|||||||
//and loads it if animation is preloaded
|
//and loads it if animation is preloaded
|
||||||
void duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup);
|
void duplicateImage(const size_t sourceGroup, const size_t sourceFrame, const size_t targetGroup);
|
||||||
|
|
||||||
|
// adjust the color of the animation, used in battle spell effects, e.g. Cloned objects
|
||||||
|
void shiftColor(const ColorShifter * shifter);
|
||||||
|
|
||||||
//add custom surface to the selected position.
|
//add custom surface to the selected position.
|
||||||
void setCustom(std::string filename, size_t frame, size_t group=0);
|
void setCustom(std::string filename, size_t frame, size_t group=0);
|
||||||
|
|
||||||
|
@ -152,6 +152,42 @@ struct ColorPutter
|
|||||||
|
|
||||||
typedef void (*BlitterWithRotationVal)(SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation);
|
typedef void (*BlitterWithRotationVal)(SDL_Surface *src,SDL_Rect srcRect, SDL_Surface * dst, SDL_Rect dstRect, ui8 rotation);
|
||||||
|
|
||||||
|
class ColorShifter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
virtual SDL_Color shiftColor(SDL_Color clr) const = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
class ColorShifterLightBlue : public ColorShifter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SDL_Color shiftColor(SDL_Color clr) const override
|
||||||
|
{
|
||||||
|
clr.b = clr.b + (255 - clr.b) / 2;
|
||||||
|
return clr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ColorShifterDeepBlue : public ColorShifter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SDL_Color shiftColor(SDL_Color clr) const override
|
||||||
|
{
|
||||||
|
clr.b = 255;
|
||||||
|
return clr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
class ColorShifterDeepRed : public ColorShifter
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
SDL_Color shiftColor(SDL_Color clr) const override
|
||||||
|
{
|
||||||
|
clr.r = 255;
|
||||||
|
return clr;
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
namespace CSDL_Ext
|
namespace CSDL_Ext
|
||||||
{
|
{
|
||||||
/// helper that will safely set and un-set ClipRect for SDL_Surface
|
/// helper that will safely set and un-set ClipRect for SDL_Surface
|
||||||
|
@ -51,7 +51,7 @@ void Clone::apply(BattleStateProxy * battleState, RNG & rng, const Mechanics * m
|
|||||||
if(clonedStack->getCount() < 1)
|
if(clonedStack->getCount() < 1)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
auto hex = m->cb->getAvaliableHex(clonedStack->creatureId(), m->casterSide);
|
auto hex = m->cb->getAvaliableHex(clonedStack->creatureId(), m->casterSide, clonedStack->getPosition());
|
||||||
|
|
||||||
if(!hex.isValid())
|
if(!hex.isValid())
|
||||||
{
|
{
|
||||||
|
Reference in New Issue
Block a user