mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-26 22:57:00 +02:00
Fixes to effects of earthquake, obstacle-creating and offensive spells
This commit is contained in:
parent
d8742dac3f
commit
58ba5f1aee
@ -980,17 +980,17 @@ CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBas
|
||||
{
|
||||
}
|
||||
|
||||
CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> pos, int effects):
|
||||
CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> hex, int effects):
|
||||
CPointEffectAnimation(_owner, sound, animationName, effects)
|
||||
{
|
||||
battlehexes = pos;
|
||||
battlehexes = hex;
|
||||
}
|
||||
|
||||
CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, BattleHex pos, int effects):
|
||||
CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, BattleHex hex, int effects):
|
||||
CPointEffectAnimation(_owner, sound, animationName, effects)
|
||||
{
|
||||
assert(pos.isValid());
|
||||
battlehexes.push_back(pos);
|
||||
assert(hex.isValid());
|
||||
battlehexes.push_back(hex);
|
||||
}
|
||||
|
||||
CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<Point> pos, int effects):
|
||||
@ -1005,6 +1005,14 @@ CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBas
|
||||
positions.push_back(pos);
|
||||
}
|
||||
|
||||
CPointEffectAnimation::CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, Point pos, BattleHex hex, int effects):
|
||||
CPointEffectAnimation(_owner, sound, animationName, effects)
|
||||
{
|
||||
assert(hex.isValid());
|
||||
battlehexes.push_back(hex);
|
||||
positions.push_back(pos);
|
||||
}
|
||||
|
||||
bool CPointEffectAnimation::init()
|
||||
{
|
||||
if(!CBattleAnimation::checkInitialConditions())
|
||||
@ -1019,9 +1027,8 @@ bool CPointEffectAnimation::init()
|
||||
return false;
|
||||
}
|
||||
|
||||
if (positions.empty() && battlehexes.empty())
|
||||
if (screenFill())
|
||||
{
|
||||
//armageddon, create screen fill
|
||||
for(int i=0; i * first->width() < owner->pos.w ; ++i)
|
||||
for(int j=0; j * first->height() < owner->pos.h ; ++j)
|
||||
positions.push_back(Point(i * first->width(), j * first->height()));
|
||||
@ -1032,35 +1039,36 @@ bool CPointEffectAnimation::init()
|
||||
be.animation = animation;
|
||||
be.currentFrame = 0;
|
||||
|
||||
for ( auto const position : positions)
|
||||
for (size_t i = 0; i < std::max(battlehexes.size(), positions.size()); ++i)
|
||||
{
|
||||
be.x = position.x;
|
||||
be.y = position.y;
|
||||
be.position = BattleHex::INVALID;
|
||||
bool hasTile = i < battlehexes.size();
|
||||
bool hasPosition = i < positions.size();
|
||||
|
||||
owner->effectsController->battleEffects.push_back(be);
|
||||
}
|
||||
|
||||
for ( auto const tile : battlehexes)
|
||||
{
|
||||
const CStack * destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(tile, false);
|
||||
|
||||
assert(tile.isValid());
|
||||
if(!tile.isValid())
|
||||
continue;
|
||||
|
||||
Rect tilePos = owner->fieldController->hexPosition(tile);
|
||||
be.position = tile;
|
||||
be.x = tilePos.x + tilePos.w/2 - first->width()/2;
|
||||
|
||||
if(destStack && destStack->doubleWide()) // Correction for 2-hex creatures.
|
||||
be.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
||||
|
||||
if (alignToBottom())
|
||||
be.y = tilePos.y + tilePos.h - first->height();
|
||||
if (hasTile && !forceOnTop())
|
||||
be.position = battlehexes[i];
|
||||
else
|
||||
be.y = tilePos.y - first->height()/2;
|
||||
be.position = BattleHex::INVALID;
|
||||
|
||||
if (hasPosition)
|
||||
{
|
||||
be.x = positions[i].x;
|
||||
be.y = positions[i].y;
|
||||
}
|
||||
else
|
||||
{
|
||||
const CStack * destStack = owner->getCurrentPlayerInterface()->cb->battleGetStackByPos(battlehexes[i], false);
|
||||
Rect tilePos = owner->fieldController->hexPosition(battlehexes[i]);
|
||||
|
||||
be.x = tilePos.x + tilePos.w/2 - first->width()/2;
|
||||
|
||||
if(destStack && destStack->doubleWide()) // Correction for 2-hex creatures.
|
||||
be.x += (destStack->side == BattleSide::ATTACKER ? -1 : 1)*tilePos.w/2;
|
||||
|
||||
if (alignToBottom())
|
||||
be.y = tilePos.y + tilePos.h - first->height();
|
||||
else
|
||||
be.y = tilePos.y - first->height()/2;
|
||||
}
|
||||
owner->effectsController->battleEffects.push_back(be);
|
||||
}
|
||||
return true;
|
||||
@ -1072,7 +1080,11 @@ void CPointEffectAnimation::nextFrame()
|
||||
playEffect();
|
||||
|
||||
if (soundFinished && effectFinished)
|
||||
{
|
||||
//remove visual effect itself only if sound has finished as well - necessary for obstacles like force field
|
||||
clearEffect();
|
||||
delete this;
|
||||
}
|
||||
}
|
||||
|
||||
bool CPointEffectAnimation::alignToBottom() const
|
||||
@ -1085,10 +1097,19 @@ bool CPointEffectAnimation::waitForSound() const
|
||||
return effectFlags & WAIT_FOR_SOUND;
|
||||
}
|
||||
|
||||
bool CPointEffectAnimation::forceOnTop() const
|
||||
{
|
||||
return effectFlags & FORCE_ON_TOP;
|
||||
}
|
||||
|
||||
bool CPointEffectAnimation::screenFill() const
|
||||
{
|
||||
return effectFlags & SCREEN_FILL;
|
||||
}
|
||||
|
||||
void CPointEffectAnimation::onEffectFinished()
|
||||
{
|
||||
effectFinished = true;
|
||||
clearEffect();
|
||||
}
|
||||
|
||||
void CPointEffectAnimation::onSoundFinished()
|
||||
@ -1118,6 +1139,9 @@ void CPointEffectAnimation::playSound()
|
||||
|
||||
void CPointEffectAnimation::playEffect()
|
||||
{
|
||||
if ( effectFinished )
|
||||
return;
|
||||
|
||||
for(auto & elem : owner->effectsController->battleEffects)
|
||||
{
|
||||
if(elem.effectID == ID)
|
||||
@ -1126,6 +1150,7 @@ void CPointEffectAnimation::playEffect()
|
||||
|
||||
if(elem.currentFrame >= elem.animation->size())
|
||||
{
|
||||
elem.currentFrame = elem.animation->size() - 1;
|
||||
onEffectFinished();
|
||||
break;
|
||||
}
|
||||
|
@ -262,6 +262,19 @@ public:
|
||||
CCastAnimation(CBattleInterface * owner_, const CStack * attacker, BattleHex dest_, const CStack * defender, const CSpell * spell);
|
||||
};
|
||||
|
||||
struct CPointEffectParameters
|
||||
{
|
||||
std::vector<Point> positions;
|
||||
std::vector<BattleHex> tiles;
|
||||
std::string animation;
|
||||
|
||||
soundBase::soundID sound = soundBase::invalid;
|
||||
BattleHex boundHex = BattleHex::INVALID;
|
||||
bool aligntoBottom = false;
|
||||
bool waitForSound = false;
|
||||
bool screenFill = false;
|
||||
};
|
||||
|
||||
/// Class that plays effect at one or more positions along with (single) sound effect
|
||||
class CPointEffectAnimation : public CBattleAnimation
|
||||
{
|
||||
@ -277,6 +290,8 @@ class CPointEffectAnimation : public CBattleAnimation
|
||||
|
||||
bool alignToBottom() const;
|
||||
bool waitForSound() const;
|
||||
bool forceOnTop() const;
|
||||
bool screenFill() const;
|
||||
|
||||
void onEffectFinished();
|
||||
void onSoundFinished();
|
||||
@ -289,7 +304,9 @@ public:
|
||||
enum EEffectFlags
|
||||
{
|
||||
ALIGN_TO_BOTTOM = 1,
|
||||
WAIT_FOR_SOUND = 2
|
||||
WAIT_FOR_SOUND = 2,
|
||||
FORCE_ON_TOP = 4,
|
||||
SCREEN_FILL = 8,
|
||||
};
|
||||
|
||||
/// Create animation with screen-wide effect
|
||||
@ -300,8 +317,10 @@ public:
|
||||
CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<Point> pos , int effects = 0);
|
||||
|
||||
/// Create animation positioned at certain hex(es)
|
||||
CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, BattleHex pos , int effects = 0);
|
||||
CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> pos, int effects = 0);
|
||||
CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, BattleHex hex , int effects = 0);
|
||||
CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, std::vector<BattleHex> hex, int effects = 0);
|
||||
|
||||
CPointEffectAnimation(CBattleInterface * _owner, soundBase::soundID sound, std::string animationName, Point pos, BattleHex hex, int effects = 0);
|
||||
~CPointEffectAnimation();
|
||||
|
||||
bool init() override;
|
||||
|
@ -583,7 +583,7 @@ void CBattleInterface::displayBattleLog(const std::vector<MetaString> & battleLo
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::displaySpellAnimationQueue(const CSpell::TAnimationQueue & q, BattleHex destinationTile)
|
||||
void CBattleInterface::displaySpellAnimationQueue(const CSpell::TAnimationQueue & q, BattleHex destinationTile, bool isHit)
|
||||
{
|
||||
for(const CSpell::TAnimation & animation : q)
|
||||
{
|
||||
@ -591,12 +591,21 @@ void CBattleInterface::displaySpellAnimationQueue(const CSpell::TAnimationQueue
|
||||
stacksController->addNewAnim(new CDummyAnimation(this, animation.pause));
|
||||
else
|
||||
{
|
||||
int flags = 0;
|
||||
|
||||
if (isHit)
|
||||
flags |= CPointEffectAnimation::FORCE_ON_TOP;
|
||||
|
||||
if (animation.verticalPosition == VerticalPosition::BOTTOM)
|
||||
flags |= CPointEffectAnimation::ALIGN_TO_BOTTOM;
|
||||
|
||||
if (!destinationTile.isValid())
|
||||
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, animation.resourceName));
|
||||
else if (animation.verticalPosition == VerticalPosition::BOTTOM)
|
||||
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, animation.resourceName, destinationTile, CPointEffectAnimation::ALIGN_TO_BOTTOM));
|
||||
flags |= CPointEffectAnimation::SCREEN_FILL;
|
||||
|
||||
if (!destinationTile.isValid())
|
||||
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, animation.resourceName, flags));
|
||||
else
|
||||
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, animation.resourceName, destinationTile));
|
||||
stacksController->addNewAnim(new CPointEffectAnimation(this, soundBase::invalid, animation.resourceName, destinationTile, flags));
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -606,7 +615,7 @@ void CBattleInterface::displaySpellCast(SpellID spellID, BattleHex destinationTi
|
||||
const CSpell * spell = spellID.toSpell();
|
||||
|
||||
if(spell)
|
||||
displaySpellAnimationQueue(spell->animationInfo.cast, destinationTile);
|
||||
displaySpellAnimationQueue(spell->animationInfo.cast, destinationTile, false);
|
||||
}
|
||||
|
||||
void CBattleInterface::displaySpellEffect(SpellID spellID, BattleHex destinationTile)
|
||||
@ -614,7 +623,7 @@ void CBattleInterface::displaySpellEffect(SpellID spellID, BattleHex destination
|
||||
const CSpell *spell = spellID.toSpell();
|
||||
|
||||
if(spell)
|
||||
displaySpellAnimationQueue(spell->animationInfo.affect, destinationTile);
|
||||
displaySpellAnimationQueue(spell->animationInfo.affect, destinationTile, false);
|
||||
}
|
||||
|
||||
void CBattleInterface::displaySpellHit(SpellID spellID, BattleHex destinationTile)
|
||||
@ -622,7 +631,7 @@ void CBattleInterface::displaySpellHit(SpellID spellID, BattleHex destinationTil
|
||||
const CSpell * spell = spellID.toSpell();
|
||||
|
||||
if(spell)
|
||||
displaySpellAnimationQueue(spell->animationInfo.hit, destinationTile);
|
||||
displaySpellAnimationQueue(spell->animationInfo.hit, destinationTile, true);
|
||||
}
|
||||
|
||||
void CBattleInterface::setAnimSpeed(int set)
|
||||
|
@ -166,7 +166,7 @@ public:
|
||||
|
||||
void displayBattleLog(const std::vector<MetaString> & battleLog);
|
||||
|
||||
void displaySpellAnimationQueue(const CSpell::TAnimationQueue & q, BattleHex destinationTile);
|
||||
void displaySpellAnimationQueue(const CSpell::TAnimationQueue & q, BattleHex destinationTile, bool isHit);
|
||||
void displaySpellCast(SpellID spellID, BattleHex destinationTile); //displays spell`s cast animation
|
||||
void displaySpellEffect(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation
|
||||
void displaySpellHit(SpellID spellID, BattleHex destinationTile); //displays spell`s affected animation
|
||||
|
@ -85,15 +85,7 @@ void CBattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr
|
||||
continue;
|
||||
}
|
||||
|
||||
std::string defname = spellObstacle->appearAnimation;
|
||||
|
||||
//TODO: sound
|
||||
//soundBase::QUIKSAND
|
||||
//soundBase::LANDMINE
|
||||
//soundBase::FORCEFLD
|
||||
//soundBase::fireWall
|
||||
|
||||
auto animation = std::make_shared<CAnimation>(defname);
|
||||
auto animation = std::make_shared<CAnimation>(spellObstacle->appearAnimation);
|
||||
animation->preload();
|
||||
|
||||
auto first = animation->getImage(0, 0);
|
||||
@ -103,10 +95,14 @@ void CBattleObstacleController::obstaclePlaced(const std::vector<std::shared_ptr
|
||||
continue;
|
||||
}
|
||||
|
||||
//TODO: sound
|
||||
//soundBase::QUIKSAND
|
||||
//soundBase::LANDMINE
|
||||
|
||||
//we assume here that effect graphics have the same size as the usual obstacle image
|
||||
// -> if we know how to blit obstacle, let's blit the effect in the same place
|
||||
Point whereTo = getObstaclePosition(first, *oi);
|
||||
owner->stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::QUIKSAND, defname, whereTo, CPointEffectAnimation::WAIT_FOR_SOUND));
|
||||
owner->stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::invalid, spellObstacle->appearAnimation, whereTo, oi->pos, CPointEffectAnimation::WAIT_FOR_SOUND));
|
||||
|
||||
//so when multiple obstacles are added, they show up one after another
|
||||
owner->waitForAnims();
|
||||
|
@ -333,7 +333,7 @@ void CBattleSiegeController::stackIsCatapulting(const CatapultAttack & ca)
|
||||
positions.push_back(owner->stacksController->getStackPositionAtHex(attackInfo.destinationTile, nullptr) + Point(99, 120));
|
||||
|
||||
|
||||
owner->stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::invalid, "SGEXPL.DEF", positions));
|
||||
owner->stacksController->addNewAnim(new CPointEffectAnimation(owner, soundBase::WALLHIT, "SGEXPL.DEF", positions));
|
||||
}
|
||||
|
||||
owner->waitForAnims();
|
||||
|
Loading…
Reference in New Issue
Block a user