1
0
mirror of https://github.com/vcmi/vcmi.git synced 2025-04-17 11:56:46 +02:00

Implemented semi-transparent spell effects

This commit is contained in:
Ivan Savenko 2024-11-17 19:48:16 +00:00
parent fd1a31253b
commit dfe6e04464
13 changed files with 41 additions and 28 deletions

View File

@ -881,9 +881,10 @@ uint32_t CastAnimation::getAttackClimaxFrame() const
return maxFrames / 2; return maxFrames / 2;
} }
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, int effects, bool reversed): EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, int effects, float transparencyFactor, bool reversed):
BattleAnimation(owner), BattleAnimation(owner),
animation(GH.renderHandler().loadAnimation(animationName, EImageBlitMode::SIMPLE)), animation(GH.renderHandler().loadAnimation(animationName, EImageBlitMode::SIMPLE)),
transparencyFactor(transparencyFactor),
effectFlags(effects), effectFlags(effects),
effectFinished(false), effectFinished(false),
reversed(reversed) reversed(reversed)
@ -892,32 +893,32 @@ EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath &
} }
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<BattleHex> hex, int effects, bool reversed): EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<BattleHex> hex, int effects, bool reversed):
EffectAnimation(owner, animationName, effects, reversed) EffectAnimation(owner, animationName, effects, 1.0f, reversed)
{ {
battlehexes = hex; battlehexes = hex;
} }
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, BattleHex hex, int effects, bool reversed): EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, BattleHex hex, int effects, float transparencyFactor, bool reversed):
EffectAnimation(owner, animationName, effects, reversed) EffectAnimation(owner, animationName, effects, transparencyFactor, reversed)
{ {
assert(hex.isValid()); assert(hex.isValid());
battlehexes.push_back(hex); battlehexes.push_back(hex);
} }
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<Point> pos, int effects, bool reversed): EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<Point> pos, int effects, bool reversed):
EffectAnimation(owner, animationName, effects, reversed) EffectAnimation(owner, animationName, effects, 1.0f, reversed)
{ {
positions = pos; positions = pos;
} }
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, int effects, bool reversed): EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, int effects, bool reversed):
EffectAnimation(owner, animationName, effects, reversed) EffectAnimation(owner, animationName, effects, 1.0f, reversed)
{ {
positions.push_back(pos); positions.push_back(pos);
} }
EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, BattleHex hex, int effects, bool reversed): EffectAnimation::EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, BattleHex hex, int effects, bool reversed):
EffectAnimation(owner, animationName, effects, reversed) EffectAnimation(owner, animationName, effects, 1.0f, reversed)
{ {
assert(hex.isValid()); assert(hex.isValid());
battlehexes.push_back(hex); battlehexes.push_back(hex);
@ -951,6 +952,7 @@ bool EffectAnimation::init()
be.effectID = ID; be.effectID = ID;
be.animation = animation; be.animation = animation;
be.currentFrame = 0; be.currentFrame = 0;
be.transparencyFactor = transparencyFactor;
be.type = reversed ? BattleEffect::AnimType::REVERSE : BattleEffect::AnimType::DEFAULT; be.type = reversed ? BattleEffect::AnimType::REVERSE : BattleEffect::AnimType::DEFAULT;
for (size_t i = 0; i < std::max(battlehexes.size(), positions.size()); ++i) for (size_t i = 0; i < std::max(battlehexes.size(), positions.size()); ++i)

View File

@ -309,9 +309,10 @@ public:
class EffectAnimation : public BattleAnimation class EffectAnimation : public BattleAnimation
{ {
std::string soundName; std::string soundName;
int effectFlags;
float transparencyFactor;
bool effectFinished; bool effectFinished;
bool reversed; bool reversed;
int effectFlags;
std::shared_ptr<CAnimation> animation; std::shared_ptr<CAnimation> animation;
std::vector<Point> positions; std::vector<Point> positions;
@ -335,14 +336,14 @@ public:
}; };
/// Create animation with screen-wide effect /// Create animation with screen-wide effect
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, int effects = 0, bool reversed = false); EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, int effects = 0, float transparencyFactor = 1.f, bool reversed = false);
/// Create animation positioned at point(s). Note that positions must be are absolute, including battleint position offset /// Create animation positioned at point(s). Note that positions must be are absolute, including battleint position offset
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos , int effects = 0, bool reversed = false); EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos , int effects = 0, bool reversed = false);
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<Point> pos , int effects = 0, bool reversed = false); EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<Point> pos , int effects = 0, bool reversed = false);
/// Create animation positioned at certain hex(es) /// Create animation positioned at certain hex(es)
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, BattleHex hex , int effects = 0, bool reversed = false); EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, BattleHex hex , int effects = 0, float transparencyFactor = 1.0f, bool reversed = false);
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<BattleHex> hex, int effects = 0, bool reversed = false); EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, std::vector<BattleHex> hex, int effects = 0, bool reversed = false);
EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, BattleHex hex, int effects = 0, bool reversed = false); EffectAnimation(BattleInterface & owner, const AnimationPath & animationName, Point pos, BattleHex hex, int effects = 0, bool reversed = false);

View File

@ -44,7 +44,7 @@ void BattleEffectsController::displayEffect(EBattleEffect effect, const BattleHe
displayEffect(effect, AudioPath(), destTile); displayEffect(effect, AudioPath(), destTile);
} }
void BattleEffectsController::displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile) void BattleEffectsController::displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile, float transparencyFactor)
{ {
size_t effectID = static_cast<size_t>(effect); size_t effectID = static_cast<size_t>(effect);
@ -52,7 +52,7 @@ void BattleEffectsController::displayEffect(EBattleEffect effect, const AudioPat
CCS->soundh->playSound( soundFile ); CCS->soundh->playSound( soundFile );
owner.stacksController->addNewAnim(new EffectAnimation(owner, customAnim, destTile)); owner.stacksController->addNewAnim(new EffectAnimation(owner, customAnim, destTile, 0, transparencyFactor));
} }
void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte) void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte)
@ -69,7 +69,7 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
switch(static_cast<BonusType>(bte.effect)) switch(static_cast<BonusType>(bte.effect))
{ {
case BonusType::HP_REGENERATION: case BonusType::HP_REGENERATION:
displayEffect(EBattleEffect::REGENERATION, AudioPath::builtin("REGENER"), stack->getPosition()); displayEffect(EBattleEffect::REGENERATION, AudioPath::builtin("REGENER"), stack->getPosition(), 0.5);
break; break;
case BonusType::MANA_DRAIN: case BonusType::MANA_DRAIN:
displayEffect(EBattleEffect::MANA_DRAIN, AudioPath::builtin("MANADRAI"), stack->getPosition()); displayEffect(EBattleEffect::MANA_DRAIN, AudioPath::builtin("MANADRAI"), stack->getPosition());
@ -78,7 +78,7 @@ void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bt
displayEffect(EBattleEffect::POISON, AudioPath::builtin("POISON"), stack->getPosition()); displayEffect(EBattleEffect::POISON, AudioPath::builtin("POISON"), stack->getPosition());
break; break;
case BonusType::FEAR: case BonusType::FEAR:
displayEffect(EBattleEffect::FEAR, AudioPath::builtin("FEAR"), stack->getPosition()); displayEffect(EBattleEffect::FEAR, AudioPath::builtin("FEAR"), stack->getPosition(), 0.5);
break; break;
case BonusType::MORALE: case BonusType::MORALE:
{ {
@ -124,6 +124,7 @@ void BattleEffectsController::collectRenderableObjects(BattleRenderer & renderer
currentFrame %= elem.animation->size(); currentFrame %= elem.animation->size();
auto img = elem.animation->getImage(currentFrame, static_cast<size_t>(elem.type)); auto img = elem.animation->getImage(currentFrame, static_cast<size_t>(elem.type));
img->setAlpha(255 * elem.transparencyFactor);
canvas.draw(img, elem.pos); canvas.draw(img, elem.pos);
}); });

View File

@ -39,7 +39,8 @@ struct BattleEffect
AnimType type; AnimType type;
Point pos; //position on the screen Point pos; //position on the screen
float currentFrame; float currentFrame = 0.0;
float transparencyFactor = 1.0;
std::shared_ptr<CAnimation> animation; std::shared_ptr<CAnimation> animation;
int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim int effectID; //uniqueID equal ot ID of appropriate CSpellEffectAnim
BattleHex tile; //Indicates if effect which hex the effect is drawn on BattleHex tile; //Indicates if effect which hex the effect is drawn on
@ -65,7 +66,7 @@ public:
//displays custom effect on the battlefield //displays custom effect on the battlefield
void displayEffect(EBattleEffect effect, const BattleHex & destTile); void displayEffect(EBattleEffect effect, const BattleHex & destTile);
void displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile); void displayEffect(EBattleEffect effect, const AudioPath & soundFile, const BattleHex & destTile, float transparencyFactor = 1.f);
void battleTriggerEffect(const BattleTriggerEffect & bte); void battleTriggerEffect(const BattleTriggerEffect & bte);

View File

@ -535,9 +535,9 @@ void BattleInterface::displaySpellAnimationQueue(const CSpell * spell, const CSp
flags |= EffectAnimation::SCREEN_FILL; flags |= EffectAnimation::SCREEN_FILL;
if (!destinationTile.isValid()) if (!destinationTile.isValid())
stacksController->addNewAnim(new EffectAnimation(*this, animation.resourceName, flags)); stacksController->addNewAnim(new EffectAnimation(*this, animation.resourceName, flags, animation.transparency));
else else
stacksController->addNewAnim(new EffectAnimation(*this, animation.resourceName, destinationTile, flags)); stacksController->addNewAnim(new EffectAnimation(*this, animation.resourceName, destinationTile, flags, animation.transparency));
} }
} }
} }

View File

@ -636,7 +636,7 @@ void BattleStacksController::stackAttacking( const StackAttackInfo & info )
{ {
owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=]() owner.addToAnimationStage(EAnimationEvents::AFTER_HIT, [=]()
{ {
owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, AudioPath::builtin("DRAINLIF"), attacker->getPosition()); owner.effectsController->displayEffect(EBattleEffect::DRAIN_LIFE, AudioPath::builtin("DRAINLIF"), attacker->getPosition(), 0.5);
}); });
} }

View File

@ -22,7 +22,8 @@
"properties" : { "properties" : {
"verticalPosition" : {"type" : "string", "enum" :["top","bottom"]}, "verticalPosition" : {"type" : "string", "enum" :["top","bottom"]},
"defName" : {"type" : "string", "format" : "animationFile"}, "defName" : {"type" : "string", "format" : "animationFile"},
"effectName" : { "type" : "string" } "effectName" : { "type" : "string" },
"transparency" : {"type" : "number", "minimum" : 0, "maximum" : 1}
}, },
"additionalProperties" : false "additionalProperties" : false
} }

View File

@ -252,7 +252,7 @@
"targetType": "NO_TARGET", "targetType": "NO_TARGET",
"animation":{ "animation":{
"hit":["SP04_"] "hit":[{ "defName" : "SP04_", "transparency" : 0.5}]
}, },
"sounds": { "sounds": {
"cast": "DEATHCLD" "cast": "DEATHCLD"

View File

@ -44,7 +44,7 @@
{"minimumAngle": 1.20 ,"defName":"C08SPW1"}, {"minimumAngle": 1.20 ,"defName":"C08SPW1"},
{"minimumAngle": 1.50 ,"defName":"C08SPW0"} {"minimumAngle": 1.50 ,"defName":"C08SPW0"}
], ],
"hit":["C08SPW5"] "hit":[ {"defName" : "C08SPW5", "transparency" : 0.5 }]
}, },
"sounds": { "sounds": {
"cast": "ICERAY" "cast": "ICERAY"
@ -309,7 +309,7 @@
"targetType" : "CREATURE", "targetType" : "CREATURE",
"animation":{ "animation":{
"affect":["C14SPA0"] "affect":[{"defName" : "C14SPA0", "transparency" : 0.5}]
}, },
"sounds": { "sounds": {
"cast": "SACBRETH" "cast": "SACBRETH"

View File

@ -483,7 +483,7 @@
"targetType" : "CREATURE", "targetType" : "CREATURE",
"animation":{ "animation":{
"affect":["C01SPE0"] "affect":[{ "defName" : "C01SPE0", "transparency" : 0.5}]
}, },
"sounds": { "sounds": {
"cast": "RESURECT" "cast": "RESURECT"

View File

@ -652,7 +652,7 @@
"targetType" : "CREATURE", "targetType" : "CREATURE",
"animation":{ "animation":{
"affect":["C07SPA1"], "affect":[{"defName" : "C07SPA1", "transparency" : 0.5}],
"projectile":[{"defName":"C07SPA0"}]//??? "projectile":[{"defName":"C07SPA0"}]//???
}, },
"sounds": { "sounds": {
@ -696,7 +696,7 @@
"targetType" : "CREATURE", "targetType" : "CREATURE",
"animation":{ "animation":{
"affect":[{"defName":"C10SPW", "verticalPosition":"bottom"}] "affect":[{"defName":"C10SPW", "verticalPosition":"bottom", "transparency" : 0.5}]
}, },
"sounds": { "sounds": {
"cast": "PRAYER" "cast": "PRAYER"

View File

@ -544,7 +544,8 @@ void CSpell::serializeJson(JsonSerializeFormat & handler)
///CSpell::AnimationInfo ///CSpell::AnimationInfo
CSpell::AnimationItem::AnimationItem() : CSpell::AnimationItem::AnimationItem() :
verticalPosition(VerticalPosition::TOP), verticalPosition(VerticalPosition::TOP),
pause(0) pause(0),
transparency(1)
{ {
} }
@ -965,10 +966,15 @@ std::shared_ptr<CSpell> CSpellHandler::loadFromJson(const std::string & scope, c
auto vPosStr = item["verticalPosition"].String(); auto vPosStr = item["verticalPosition"].String();
if("bottom" == vPosStr) if("bottom" == vPosStr)
newItem.verticalPosition = VerticalPosition::BOTTOM; newItem.verticalPosition = VerticalPosition::BOTTOM;
if (item["transparency"].isNumber())
newItem.transparency = item["transparency"].Float();
else
newItem.transparency = 1.0;
} }
else if(item.isNumber()) else if(item.isNumber())
{ {
newItem.pause = static_cast<int>(item.Float()); newItem.pause = item.Integer();
} }
q.push_back(newItem); q.push_back(newItem);

View File

@ -74,6 +74,7 @@ public:
AnimationPath resourceName; AnimationPath resourceName;
std::string effectName; std::string effectName;
VerticalPosition verticalPosition; VerticalPosition verticalPosition;
float transparency;
int pause; int pause;
AnimationItem(); AnimationItem();