mirror of
https://github.com/vcmi/vcmi.git
synced 2024-12-24 22:14:36 +02:00
Added configurable animation for SPELL_LIKE_ATTACK
This commit is contained in:
parent
943a5bf0d3
commit
d94f15bdf4
@ -876,7 +876,7 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
|
||||
|
||||
std::vector<StackAttackedInfo> arg;
|
||||
for(auto & elem : bsa)
|
||||
{
|
||||
@ -887,6 +887,11 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
|
||||
if (defender && !elem.isSecondary())
|
||||
battleInt->displayEffect(elem.effect, defender->position);
|
||||
}
|
||||
if(elem.isSpell())
|
||||
{
|
||||
if (defender)
|
||||
battleInt->displaySpellEffect(elem.spellID, defender->position);
|
||||
}
|
||||
//FIXME: why action is deleted during enchanter cast?
|
||||
bool remoteAttack = false;
|
||||
|
||||
@ -968,6 +973,15 @@ void CPlayerInterface::battleAttack(const BattleAttack *ba)
|
||||
const CStack * attacked = cb->battleGetStackByID(ba->bsa.begin()->stackAttacked);
|
||||
battleInt->stackAttacking( attacker, ba->counter() ? curAction->destinationTile + shift : curAction->additionalInfo, attacked, false);
|
||||
}
|
||||
|
||||
battleInt->waitForAnims();
|
||||
|
||||
if(ba->spellLike())
|
||||
{
|
||||
//display hit animation
|
||||
SpellID spellID = ba->spellID;
|
||||
battleInt->displaySpellHit(spellID,curAction->destinationTile);
|
||||
}
|
||||
}
|
||||
void CPlayerInterface::battleObstaclePlaced(const CObstacleInstance &obstacle)
|
||||
{
|
||||
|
@ -1226,7 +1226,8 @@ void CBattleInterface::displayBattleFinished()
|
||||
|
||||
void CBattleInterface::spellCast( const BattleSpellCast * sc )
|
||||
{
|
||||
const CSpell &spell = *CGI->spellh->objects[sc->id];
|
||||
const SpellID spellID(sc->id);
|
||||
const CSpell &spell = * spellID.toSpell();
|
||||
|
||||
const std::string& castSoundPath = spell.getCastSound();
|
||||
|
||||
@ -1289,11 +1290,7 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
|
||||
}
|
||||
waitForAnims();
|
||||
|
||||
//queuing hit animation
|
||||
for(const CSpell::TAnimation & animation : spell.animationInfo.hit)
|
||||
{
|
||||
addNewAnim(new CSpellEffectAnimation(this, animation.resourceName, sc->tile, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
||||
}
|
||||
displaySpellHit(spellID, sc->tile);
|
||||
|
||||
//queuing affect /resist animation
|
||||
for (auto & elem : sc->affectedCres)
|
||||
@ -1301,16 +1298,9 @@ void CBattleInterface::spellCast( const BattleSpellCast * sc )
|
||||
BattleHex position = curInt->cb->battleGetStackByID(elem, false)->position;
|
||||
|
||||
if(vstd::contains(sc->resisted,elem))
|
||||
{
|
||||
displayEffect(78, position);
|
||||
}
|
||||
else
|
||||
{
|
||||
for(const CSpell::TAnimation & animation : spell.animationInfo.affect)
|
||||
{
|
||||
addNewAnim(new CSpellEffectAnimation(this, animation.resourceName, position, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
||||
}
|
||||
}
|
||||
displaySpellEffect(spellID, position);
|
||||
}
|
||||
|
||||
switch(sc->id)
|
||||
@ -1570,6 +1560,33 @@ void CBattleInterface::displayEffect(ui32 effect, int destTile, bool areaEffect)
|
||||
addNewAnim(new CSpellEffectAnimation(this, effect, destTile, 0, 0, false));
|
||||
}
|
||||
|
||||
void CBattleInterface::displaySpellEffect(SpellID spellID, BattleHex destinationTile, bool areaEffect)
|
||||
{
|
||||
const CSpell * spell = spellID.toSpell();
|
||||
|
||||
if(spell == nullptr)
|
||||
return;
|
||||
|
||||
for(const CSpell::TAnimation & animation : spell->animationInfo.affect)
|
||||
{
|
||||
addNewAnim(new CSpellEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
||||
}
|
||||
}
|
||||
|
||||
void CBattleInterface::displaySpellHit(SpellID spellID, BattleHex destinationTile, bool areaEffect)
|
||||
{
|
||||
const CSpell * spell = spellID.toSpell();
|
||||
|
||||
if(spell == nullptr)
|
||||
return;
|
||||
|
||||
for(const CSpell::TAnimation & animation : spell->animationInfo.hit)
|
||||
{
|
||||
addNewAnim(new CSpellEffectAnimation(this, animation.resourceName, destinationTile, false, animation.verticalPosition == VerticalPosition::BOTTOM));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CBattleInterface::battleTriggerEffect(const BattleTriggerEffect & bte)
|
||||
{
|
||||
const CStack * stack = curInt->cb->battleGetStackByID(bte.stackID);
|
||||
|
@ -318,7 +318,10 @@ public:
|
||||
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 castThisSpell(int spellID); //called when player has chosen a spell from spellbook
|
||||
void displayEffect(ui32 effect, int destTile, bool areaEffect = true); //displays effect of a spell on the battlefield; affected: true - attacker. false - defender
|
||||
void displayEffect(ui32 effect, int destTile, bool areaEffect = true); //displays custom effect on the battlefield
|
||||
void displaySpellEffect(SpellID spellID, BattleHex destinationTile, bool areaEffect = true); //displays spell`s affected animation
|
||||
void displaySpellHit(SpellID spellID, BattleHex destinationTile, bool areaEffect = true); //displays spell`s affected animation
|
||||
|
||||
void battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
void setBattleCursor(const int myNumber); //really complex and messy, sets attackingHex
|
||||
void endAction(const BattleAction* action);
|
||||
|
@ -90,11 +90,11 @@
|
||||
{ "id": 59, "defnames": [ "C09SPF0.DEF" ] },
|
||||
{ "id": 62, "defnames": [ "C07SPF60.DEF", "C07SPF61.DEF", "C07SPF62.DEF" ] },
|
||||
{ "id": 64, "defnames": [ "C20SPX.DEF" ] }, //merged
|
||||
{ "id": 67, "defnames": [ "SP11_.DEF" ] },
|
||||
{ "id": 68, "defnames": [ "SP02_.DEF" ] },
|
||||
{ "id": 69, "defnames": [ "SP05_.DEF" ] },
|
||||
{ "id": 71, "defnames": [ "SP01_.DEF" ] },
|
||||
{ "id": 72, "defnames": [ "SP04_.DEF" ] },
|
||||
{ "id": 67, "defnames": [ "SP11_.DEF" ] }, //merged
|
||||
{ "id": 68, "defnames": [ "SP02_.DEF" ] }, //merged
|
||||
{ "id": 69, "defnames": [ "SP05_.DEF" ] }, //merged
|
||||
{ "id": 71, "defnames": [ "SP01_.DEF" ] }, //merged
|
||||
{ "id": 72, "defnames": [ "SP04_.DEF" ] }, //merged
|
||||
{ "id": 73, "defnames": [ "SP03_.DEF" ] },
|
||||
{ "id": 74, "defnames": [ "SP12_.DEF" ] },
|
||||
{ "id": 75, "defnames": [ "SP07_A.DEF" ] },
|
||||
@ -102,8 +102,8 @@
|
||||
{ "id": 77, "defnames": [ "SP08_.DEF" ] },
|
||||
{ "id": 78, "defnames": [ "SP09_.DEF" ] },
|
||||
{ "id": 79, "defnames": [ "C01SPE0.DEF" ] },//merged
|
||||
{ "id": 80, "defnames": [ "C07SPE0.DEF" ] },
|
||||
{ "id": 81, "defnames": [ "C17SPW0.DEF" ] },
|
||||
{ "id": 80, "defnames": [ "C07SPE0.DEF" ] },//merged
|
||||
{ "id": 81, "defnames": [ "C17SPW0.DEF" ] },//merged
|
||||
{ "id": 82, "defnames": [ "C09SPF3.DEF" ] },
|
||||
{ "id": 84, "defnames": [ "ZMGC02.DEF" ] }
|
||||
]
|
||||
|
@ -107,6 +107,13 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"texts":{
|
||||
"type": "object",
|
||||
|
||||
|
||||
"additionalProperties" : false
|
||||
}
|
||||
},
|
||||
|
||||
|
@ -3,6 +3,9 @@
|
||||
"index" : 70,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 70,
|
||||
"animation":{
|
||||
//need special animation
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "PARALYZE"
|
||||
},
|
||||
@ -36,6 +39,9 @@
|
||||
"index" : 71,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 67,
|
||||
"animation":{
|
||||
"affect":["SP11_"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "POISON"
|
||||
},
|
||||
@ -71,6 +77,9 @@
|
||||
"index" : 72,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 68,
|
||||
"animation":{
|
||||
"affect":["SP02_"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "BIND"
|
||||
},
|
||||
@ -95,6 +104,9 @@
|
||||
"index" : 73,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 69,
|
||||
"animation":{
|
||||
"affect":["SP05_"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "DISEASE"
|
||||
},
|
||||
@ -130,6 +142,9 @@
|
||||
"index" : 74,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 70,
|
||||
"animation":{
|
||||
//missing
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "PARALYZE"
|
||||
},
|
||||
@ -163,6 +178,9 @@
|
||||
"index" : 75,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 71,
|
||||
"animation":{
|
||||
"affect":["SP01_"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "AGE"
|
||||
},
|
||||
@ -192,6 +210,9 @@
|
||||
"index" : 76,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 72,
|
||||
"animation":{
|
||||
"hit":["SP04_"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "DEATHCLD"
|
||||
},
|
||||
@ -212,6 +233,9 @@
|
||||
"index" : 77,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 38,
|
||||
"animation":{
|
||||
"affect":[{"defName":"C03SPA0", "verticalPosition":"bottom"}, "C11SPA1"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "LIGHTBLT"
|
||||
},
|
||||
@ -230,6 +254,9 @@
|
||||
"index" : 78,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 41,
|
||||
"animation":{
|
||||
"affect":["C05SPW"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "DISPELL"
|
||||
},
|
||||
@ -247,6 +274,9 @@
|
||||
"index" : 79,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 80,
|
||||
"animation":{
|
||||
"affect":["C07SPE0"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "DEATHSTR"
|
||||
},
|
||||
@ -267,6 +297,9 @@
|
||||
"index" : 80,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 81,
|
||||
"animation":{
|
||||
"affect":["C17SPW0"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "ACID"
|
||||
},
|
||||
@ -293,6 +326,9 @@
|
||||
"index" : 81,
|
||||
"targetType": "NO_TARGET",
|
||||
"anim" : 81,
|
||||
"animation":{
|
||||
//???
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "ACID"
|
||||
},
|
||||
|
@ -68,7 +68,7 @@
|
||||
"targetType": "CREATURE",
|
||||
"anim" : 38,
|
||||
"animation":{
|
||||
"hit":[{"defName":"C03SPA0", "verticalPosition":"bottom"}, "C11SPA1"]
|
||||
"affect":[{"defName":"C03SPA0", "verticalPosition":"bottom"}, "C11SPA1"]
|
||||
},
|
||||
"sounds": {
|
||||
"cast": "LIGHTBLT"
|
||||
|
@ -87,6 +87,11 @@ CCreature * CreatureID::toCreature() const
|
||||
|
||||
CSpell * SpellID::toSpell() const
|
||||
{
|
||||
if(num < 0 || num >= VLC->spellh->objects.size())
|
||||
{
|
||||
logGlobal->errorStream() << "Unable to get spell of invalid ID " << int(num);
|
||||
return nullptr;
|
||||
}
|
||||
return VLC->spellh->objects[*this];
|
||||
}
|
||||
|
||||
|
@ -1320,16 +1320,18 @@ struct StacksHealedOrResurrected : public CPackForClient //3013
|
||||
|
||||
struct BattleStackAttacked : public CPackForClient//3005
|
||||
{
|
||||
BattleStackAttacked(){flags = 0; type = 3005;};
|
||||
BattleStackAttacked():
|
||||
flags(0), spellID(SpellID::NONE){type=3005;};
|
||||
void applyFirstCl(CClient * cl);
|
||||
//void applyCl(CClient *cl);
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
|
||||
ui32 stackAttacked, attackerID;
|
||||
ui32 newAmount, newHP, killedAmount, damageAmount;
|
||||
enum EFlags {KILLED = 1, EFFECT = 2, SECONDARY = 4, REBIRTH = 8, CLONE_KILLED = 16};
|
||||
ui8 flags; //uses EFlags (above)
|
||||
enum EFlags {KILLED = 1, EFFECT = 2/*deprecated */, SECONDARY = 4, REBIRTH = 8, CLONE_KILLED = 16, SPELL_EFFECT = 32 /*, BONUS_EFFECT = 64 */};
|
||||
ui32 flags; //uses EFlags (above)
|
||||
ui32 effect; //set only if flag EFFECT is set
|
||||
SpellID spellID; //only if flag SPELL_EFFECT is set
|
||||
std::vector<StacksHealedOrResurrected> healedStacks; //used when life drain
|
||||
|
||||
|
||||
@ -1349,6 +1351,11 @@ struct BattleStackAttacked : public CPackForClient//3005
|
||||
{
|
||||
return flags & SECONDARY;
|
||||
}
|
||||
///Attacked with spell (SPELL_LIKE_ATTACK)
|
||||
bool isSpell() const
|
||||
{
|
||||
return flags & SPELL_EFFECT;
|
||||
}
|
||||
bool willRebirth() const//resurrection, e.g. Phoenix
|
||||
{
|
||||
return flags & REBIRTH;
|
||||
@ -1361,6 +1368,7 @@ struct BattleStackAttacked : public CPackForClient//3005
|
||||
{
|
||||
h & stackAttacked & attackerID & newAmount & newHP & flags & killedAmount & damageAmount & effect
|
||||
& healedStacks;
|
||||
h & spellID;
|
||||
}
|
||||
bool operator<(const BattleStackAttacked &b) const
|
||||
{
|
||||
@ -1370,15 +1378,17 @@ struct BattleStackAttacked : public CPackForClient//3005
|
||||
|
||||
struct BattleAttack : public CPackForClient//3006
|
||||
{
|
||||
BattleAttack(){flags = 0; type = 3006;};
|
||||
BattleAttack(): flags(0), spellID(SpellID::NONE){type = 3006;};
|
||||
void applyFirstCl(CClient *cl);
|
||||
DLL_LINKAGE void applyGs(CGameState *gs);
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
std::vector<BattleStackAttacked> bsa;
|
||||
ui32 stackAttacking;
|
||||
ui8 flags; //uses Eflags (below)
|
||||
enum EFlags{SHOT = 1, COUNTER = 2, LUCKY = 4, UNLUCKY = 8, BALLISTA_DOUBLE_DMG = 16, DEATH_BLOW = 32};
|
||||
ui32 flags; //uses Eflags (below)
|
||||
enum EFlags{SHOT = 1, COUNTER = 2, LUCKY = 4, UNLUCKY = 8, BALLISTA_DOUBLE_DMG = 16, DEATH_BLOW = 32, SPELL_LIKE = 64};
|
||||
|
||||
SpellID spellID; //for SPELL_LIKE
|
||||
|
||||
bool shot() const//distance attack - decrease number of shots
|
||||
{
|
||||
@ -1404,13 +1414,17 @@ struct BattleAttack : public CPackForClient//3006
|
||||
{
|
||||
return flags & DEATH_BLOW;
|
||||
}
|
||||
bool spellLike() const
|
||||
{
|
||||
return flags & SPELL_LIKE;
|
||||
}
|
||||
//bool killed() //if target stack was killed
|
||||
//{
|
||||
// return bsa.killed();
|
||||
//}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & bsa & stackAttacking & flags;
|
||||
h & bsa & stackAttacking & flags & spellID;
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -794,11 +794,14 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
||||
}
|
||||
|
||||
const Bonus * bonus = att->getBonusLocalFirst(Selector::type(Bonus::SPELL_LIKE_ATTACK));
|
||||
if (bonus && (bat.shot())) //TODO: make it work in meele?
|
||||
{
|
||||
bat.bsa.front().flags |= BattleStackAttacked::EFFECT;
|
||||
bat.bsa.front().effect = VLC->spellh->objects.at(bonus->subtype)->mainEffectAnim; //hopefully it does not interfere with any other effect?
|
||||
|
||||
if (bonus && (bat.shot())) //TODO: make it work in melee?
|
||||
{
|
||||
//this is need for displaying hit animation
|
||||
bat.flags |= BattleAttack::SPELL_LIKE;
|
||||
bat.spellID = SpellID(bonus->subtype);
|
||||
|
||||
//TODO: should spell override creature`s projectile?
|
||||
|
||||
std::set<const CStack*> attackedCreatures = SpellID(bonus->subtype).toSpell()->getAffectedStacks(gs->curB, ECastingMode::SPELL_LIKE_ATTACK, att->owner, bonus->val, targetHex);
|
||||
|
||||
//TODO: get exact attacked hex for defender
|
||||
@ -810,6 +813,18 @@ void CGameHandler::prepareAttack(BattleAttack &bat, const CStack *att, const CSt
|
||||
applyBattleEffects(bat, att, stack, distance, true);
|
||||
}
|
||||
}
|
||||
|
||||
//now add effect info for all attacked stacks
|
||||
for(BattleStackAttacked & bsa : bat.bsa)
|
||||
{
|
||||
if(bsa.attackerID == att->ID) //this is our attack and not f.e. fire shield
|
||||
{
|
||||
//this is need for displaying affect animation
|
||||
bsa.flags |= BattleStackAttacked::SPELL_EFFECT;
|
||||
bsa.spellID = SpellID(bonus->subtype);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
void CGameHandler::applyBattleEffects(BattleAttack &bat, const CStack *att, const CStack *def, int distance, bool secondary) //helper function for prepareAttack
|
||||
|
Loading…
Reference in New Issue
Block a user