mirror of
https://github.com/vcmi/vcmi.git
synced 2025-01-26 03:52:01 +02:00
All battle effects are now fully client sided
This commit is contained in:
parent
ced2ece954
commit
deffba01b9
@ -707,7 +707,7 @@ void CPlayerInterface::battleStart(const CCreatureSet *army1, const CCreatureSet
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects)
|
||||
void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units)
|
||||
{
|
||||
EVENT_HANDLER_CALLED_BY_CLIENT;
|
||||
BATTLE_EVENT_POSSIBLE_RETURN;
|
||||
@ -747,8 +747,6 @@ void CPlayerInterface::battleUnitsChanged(const std::vector<UnitChanges> & units
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
battleInt->effectsController->displayCustomEffects(customEffects);
|
||||
}
|
||||
|
||||
void CPlayerInterface::battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles)
|
||||
@ -962,15 +960,12 @@ void CPlayerInterface::battleStacksAttacked(const std::vector<BattleStackAttacke
|
||||
info.attacker = attacker;
|
||||
info.damageDealt = elem.damageAmount;
|
||||
info.amountKilled = elem.killedAmount;
|
||||
info.battleEffect = EBattleEffect::INVALID;
|
||||
info.spellEffect = SpellID::NONE;
|
||||
info.indirectAttack = ranged;
|
||||
info.killed = elem.killed();
|
||||
info.rebirth = elem.willRebirth();
|
||||
info.cloneKilled = elem.cloneKilled();
|
||||
|
||||
if(elem.isEffect() && !elem.isSecondary())
|
||||
info.battleEffect = EBattleEffect::EBattleEffect(elem.effect);
|
||||
info.fireShield = elem.fireShield();
|
||||
|
||||
if (elem.isSpell())
|
||||
info.spellEffect = elem.spellID;
|
||||
|
@ -200,7 +200,7 @@ public:
|
||||
void battleStacksAttacked(const std::vector<BattleStackAttacked> & bsa, bool ranged) override;
|
||||
void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) override; //called by engine just before battle starts; side=0 - left, side=1 - right
|
||||
void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side) override; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects) override;
|
||||
void battleUnitsChanged(const std::vector<UnitChanges> & units) override;
|
||||
void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles) override;
|
||||
void battleCatapultAttacked(const CatapultAttack & ca) override; //called when catapult makes an attack
|
||||
void battleGateStateChanged(const EGateState state) override;
|
||||
|
@ -782,7 +782,7 @@ void BattleResultsApplied::applyCl(CClient *cl)
|
||||
|
||||
void BattleUnitsChanged::applyCl(CClient * cl)
|
||||
{
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, changedStacks, customEffects);
|
||||
callBattleInterfaceIfPresentForBothSides(cl, &IBattleEventsReceiver::battleUnitsChanged, changedStacks);
|
||||
}
|
||||
|
||||
void BattleObstaclesChanged::applyCl(CClient *cl)
|
||||
|
@ -9,6 +9,27 @@
|
||||
*/
|
||||
#pragma once
|
||||
|
||||
enum class EBattleEffect
|
||||
{
|
||||
// list of battle effects that have hardcoded triggers
|
||||
MAGIC_MIRROR = 3,
|
||||
FIRE_SHIELD = 11,
|
||||
FEAR = 15,
|
||||
GOOD_LUCK = 18,
|
||||
GOOD_MORALE = 20,
|
||||
BAD_MORALE = 30,
|
||||
BAD_LUCK = 48,
|
||||
RESURRECT = 50,
|
||||
DRAIN_LIFE = 52,
|
||||
POISON = 67,
|
||||
DEATH_BLOW = 73,
|
||||
REGENERATION = 74,
|
||||
MANA_DRAIN = 77,
|
||||
RESISTANCE = 78,
|
||||
|
||||
INVALID = -1,
|
||||
};
|
||||
|
||||
enum class EAnimationEvents {
|
||||
OPENING = 0, // TODO battle opening sound is playing
|
||||
ACTION = 1, // there are any ongoing animations
|
||||
@ -22,27 +43,6 @@ enum class EAnimationEvents {
|
||||
COUNT
|
||||
};
|
||||
|
||||
namespace EBattleEffect
|
||||
{
|
||||
enum EBattleEffect
|
||||
{
|
||||
// list of battle effects that have hardcoded triggers
|
||||
FEAR = 15,
|
||||
GOOD_LUCK = 18,
|
||||
GOOD_MORALE = 20,
|
||||
BAD_MORALE = 30,
|
||||
BAD_LUCK = 48,
|
||||
RESURRECT = 50,
|
||||
DRAIN_LIFE = 52,
|
||||
POISON = 67,
|
||||
DEATH_BLOW = 73,
|
||||
REGENERATION = 74,
|
||||
MANA_DRAIN = 77,
|
||||
|
||||
INVALID = -1,
|
||||
};
|
||||
}
|
||||
|
||||
enum class EHeroAnimType
|
||||
{
|
||||
HOLDING = 0,
|
||||
|
@ -35,31 +35,20 @@ BattleEffectsController::BattleEffectsController(BattleInterface & owner):
|
||||
owner(owner)
|
||||
{}
|
||||
|
||||
void BattleEffectsController::displayEffect(EBattleEffect::EBattleEffect effect, const BattleHex & destTile)
|
||||
void BattleEffectsController::displayEffect(EBattleEffect effect, const BattleHex & destTile)
|
||||
{
|
||||
displayEffect(effect, soundBase::invalid, destTile);
|
||||
}
|
||||
|
||||
void BattleEffectsController::displayEffect(EBattleEffect::EBattleEffect effect, uint32_t soundID, const BattleHex & destTile)
|
||||
void BattleEffectsController::displayEffect(EBattleEffect effect, uint32_t soundID, const BattleHex & destTile)
|
||||
{
|
||||
std::string customAnim = graphics->battleACToDef[effect][0];
|
||||
size_t effectID = static_cast<size_t>(effect);
|
||||
|
||||
std::string customAnim = graphics->battleACToDef[effectID][0];
|
||||
|
||||
owner.stacksController->addNewAnim(new PointEffectAnimation(owner, soundBase::stringsList()[soundID], customAnim, destTile));
|
||||
}
|
||||
|
||||
void BattleEffectsController::displayCustomEffects(const std::vector<CustomEffectInfo> & customEffects)
|
||||
{
|
||||
for(const CustomEffectInfo & one : customEffects)
|
||||
{
|
||||
const CStack * s = owner.curInt->cb->battleGetStackByID(one.stack, false);
|
||||
|
||||
assert(s);
|
||||
assert(one.effect != 0);
|
||||
|
||||
displayEffect(EBattleEffect::EBattleEffect(one.effect), soundBase::soundID(one.sound), s->getPosition());
|
||||
}
|
||||
}
|
||||
|
||||
void BattleEffectsController::battleTriggerEffect(const BattleTriggerEffect & bte)
|
||||
{
|
||||
assert(owner.getAnimationCondition(EAnimationEvents::ACTION) == false);
|
||||
|
@ -15,7 +15,6 @@
|
||||
VCMI_LIB_NAMESPACE_BEGIN
|
||||
|
||||
class BattleAction;
|
||||
struct CustomEffectInfo;
|
||||
struct BattleTriggerEffect;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
@ -49,11 +48,9 @@ public:
|
||||
|
||||
void startAction(const BattleAction* action);
|
||||
|
||||
void displayCustomEffects(const std::vector<CustomEffectInfo> & customEffects);
|
||||
|
||||
//displays custom effect on the battlefield
|
||||
void displayEffect(EBattleEffect::EBattleEffect effect, const BattleHex & destTile);
|
||||
void displayEffect(EBattleEffect::EBattleEffect effect, uint32_t soundID, const BattleHex & destTile);
|
||||
void displayEffect(EBattleEffect effect, const BattleHex & destTile);
|
||||
void displayEffect(EBattleEffect effect, uint32_t soundID, const BattleHex & destTile);
|
||||
|
||||
void battleTriggerEffect(const BattleTriggerEffect & bte);
|
||||
|
||||
|
@ -550,17 +550,22 @@ void BattleInterface::spellCast(const BattleSpellCast * sc)
|
||||
}
|
||||
}
|
||||
|
||||
//queuing additional animation (magic mirror / resistance)
|
||||
for(auto & elem : sc->customEffects)
|
||||
for(auto & elem : sc->reflectedCres)
|
||||
{
|
||||
auto stack = curInt->cb->battleGetStackByID(elem.stack, false);
|
||||
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
||||
assert(stack);
|
||||
if(stack)
|
||||
{
|
||||
executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
||||
effectsController->displayEffect(EBattleEffect::EBattleEffect(elem.effect), stack->getPosition());
|
||||
effectsController->displayEffect(EBattleEffect::MAGIC_MIRROR, stack->getPosition());
|
||||
});
|
||||
}
|
||||
|
||||
for(auto & elem : sc->resistedCres)
|
||||
{
|
||||
auto stack = curInt->cb->battleGetStackByID(elem, false);
|
||||
assert(stack);
|
||||
executeOnAnimationCondition(EAnimationEvents::HIT, true, [=](){
|
||||
effectsController->displayEffect(EBattleEffect::RESISTANCE, stack->getPosition());
|
||||
});
|
||||
}
|
||||
|
||||
//mana absorption
|
||||
|
@ -29,7 +29,6 @@ struct CatapultAttack;
|
||||
struct BattleTriggerEffect;
|
||||
struct BattleHex;
|
||||
struct InfoAboutHero;
|
||||
struct CustomEffectInfo;
|
||||
|
||||
VCMI_LIB_NAMESPACE_END
|
||||
|
||||
@ -62,14 +61,13 @@ struct StackAttackedInfo
|
||||
|
||||
int64_t damageDealt;
|
||||
uint32_t amountKilled;
|
||||
|
||||
EBattleEffect::EBattleEffect battleEffect;
|
||||
SpellID spellEffect;
|
||||
|
||||
bool indirectAttack; //if true, stack was attacked indirectly - spell or ranged attack
|
||||
bool killed; //if true, stack has been killed
|
||||
bool rebirth; //if true, play rebirth animation after all
|
||||
bool cloneKilled;
|
||||
bool fireShield;
|
||||
};
|
||||
|
||||
struct StackAttackInfo
|
||||
@ -78,7 +76,6 @@ struct StackAttackInfo
|
||||
const CStack *defender;
|
||||
std::vector< const CStack *> secondaryDefender;
|
||||
|
||||
//EBattleEffect::EBattleEffect battleEffect;
|
||||
SpellID spellEffect;
|
||||
BattleHex tile;
|
||||
|
||||
|
@ -444,8 +444,8 @@ void BattleStacksController::stacksAreAttacked(std::vector<StackAttackedInfo> at
|
||||
else
|
||||
addNewAnim(new HittedAnimation(owner, attackedInfo.defender));
|
||||
|
||||
if (attackedInfo.battleEffect != EBattleEffect::INVALID)
|
||||
owner.effectsController->displayEffect(EBattleEffect::EBattleEffect(attackedInfo.battleEffect), attackedInfo.defender->getPosition());
|
||||
if (attackedInfo.fireShield)
|
||||
owner.effectsController->displayEffect(EBattleEffect::FIRE_SHIELD, attackedInfo.attacker->getPosition());
|
||||
|
||||
if (attackedInfo.spellEffect != SpellID::NONE)
|
||||
owner.displaySpellEffect(attackedInfo.spellEffect, attackedInfo.defender->getPosition());
|
||||
|
@ -225,9 +225,9 @@ void CAdventureAI::battleEnd(const BattleResult * br)
|
||||
battleAI.reset();
|
||||
}
|
||||
|
||||
void CAdventureAI::battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects)
|
||||
void CAdventureAI::battleUnitsChanged(const std::vector<UnitChanges> & units)
|
||||
{
|
||||
battleAI->battleUnitsChanged(units, customEffects);
|
||||
battleAI->battleUnitsChanged(units);
|
||||
}
|
||||
|
||||
BattleAction CAdventureAI::activeStack(const CStack * stack)
|
||||
|
@ -164,7 +164,7 @@ public:
|
||||
virtual void battleAttack(const BattleAttack *ba) override;
|
||||
virtual void battleSpellCast(const BattleSpellCast *sc) override;
|
||||
virtual void battleEnd(const BattleResult *br) override;
|
||||
virtual void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects) override;
|
||||
virtual void battleUnitsChanged(const std::vector<UnitChanges> & units) override;
|
||||
|
||||
virtual void saveGame(BinarySerializer & h, const int version) override;
|
||||
virtual void loadGame(BinaryDeserializer & h, const int version) override;
|
||||
|
@ -49,7 +49,6 @@ struct CObstacleInstance;
|
||||
struct CPackForServer;
|
||||
class EVictoryLossCheckResult;
|
||||
struct MetaString;
|
||||
struct CustomEffectInfo;
|
||||
class ObstacleChanges;
|
||||
class UnitChanges;
|
||||
|
||||
@ -70,7 +69,7 @@ public:
|
||||
virtual void battleTriggerEffect(const BattleTriggerEffect & bte){}; //called for various one-shot effects
|
||||
virtual void battleStartBefore(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2) {}; //called just before battle start
|
||||
virtual void battleStart(const CCreatureSet *army1, const CCreatureSet *army2, int3 tile, const CGHeroInstance *hero1, const CGHeroInstance *hero2, bool side){}; //called by engine when battle starts; side=0 - left, side=1 - right
|
||||
virtual void battleUnitsChanged(const std::vector<UnitChanges> & units, const std::vector<CustomEffectInfo> & customEffects){};
|
||||
virtual void battleUnitsChanged(const std::vector<UnitChanges> & units){};
|
||||
virtual void battleObstaclesChanged(const std::vector<ObstacleChanges> & obstacles){};
|
||||
virtual void battleCatapultAttacked(const CatapultAttack & ca){}; //called when catapult makes an attack
|
||||
virtual void battleGateStateChanged(const EGateState state){};
|
||||
|
@ -1557,12 +1557,10 @@ struct BattleUnitsChanged : public CPackForClient
|
||||
void applyCl(CClient *cl);
|
||||
|
||||
std::vector<UnitChanges> changedStacks;
|
||||
std::vector<CustomEffectInfo> customEffects;
|
||||
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & changedStacks;
|
||||
h & customEffects;
|
||||
}
|
||||
};
|
||||
|
||||
@ -1575,7 +1573,6 @@ struct BattleStackAttacked
|
||||
damageAmount(0),
|
||||
newState(),
|
||||
flags(0),
|
||||
effect(0),
|
||||
spellID(SpellID::NONE)
|
||||
{};
|
||||
|
||||
@ -1586,9 +1583,8 @@ struct BattleStackAttacked
|
||||
ui32 killedAmount;
|
||||
int64_t damageAmount;
|
||||
UnitChanges newState;
|
||||
enum EFlags {KILLED = 1, EFFECT = 2/*deprecated */, SECONDARY = 4, REBIRTH = 8, CLONE_KILLED = 16, SPELL_EFFECT = 32 /*, BONUS_EFFECT = 64 */};
|
||||
enum EFlags {KILLED = 1, SECONDARY = 2, REBIRTH = 4, CLONE_KILLED = 8, SPELL_EFFECT = 16, FIRE_SHIELD = 32, };
|
||||
ui32 flags; //uses EFlags (above)
|
||||
ui32 effect; //set only if flag EFFECT is set
|
||||
SpellID spellID; //only if flag SPELL_EFFECT is set
|
||||
|
||||
bool killed() const//if target stack was killed
|
||||
@ -1599,10 +1595,6 @@ struct BattleStackAttacked
|
||||
{
|
||||
return flags & CLONE_KILLED;
|
||||
}
|
||||
bool isEffect() const//if stack has been attacked by a spell
|
||||
{
|
||||
return flags & EFFECT;
|
||||
}
|
||||
bool isSecondary() const//if stack was not a primary target (receives no spell effects)
|
||||
{
|
||||
return flags & SECONDARY;
|
||||
@ -1616,6 +1608,10 @@ struct BattleStackAttacked
|
||||
{
|
||||
return flags & REBIRTH;
|
||||
}
|
||||
bool fireShield() const
|
||||
{
|
||||
return flags & FIRE_SHIELD;
|
||||
}
|
||||
template <typename Handler> void serialize(Handler &h, const int version)
|
||||
{
|
||||
h & stackAttacked;
|
||||
@ -1624,7 +1620,6 @@ struct BattleStackAttacked
|
||||
h & flags;
|
||||
h & killedAmount;
|
||||
h & damageAmount;
|
||||
h & effect;
|
||||
h & spellID;
|
||||
}
|
||||
bool operator<(const BattleStackAttacked &b) const
|
||||
@ -1737,8 +1732,9 @@ struct BattleSpellCast : public CPackForClient
|
||||
SpellID spellID; //id of spell
|
||||
ui8 manaGained; //mana channeling ability
|
||||
BattleHex tile; //destination tile (may not be set in some global/mass spells
|
||||
std::vector<CustomEffectInfo> customEffects;
|
||||
std::set<ui32> affectedCres; //ids of creatures affected by this spell, generally used if spell does not set any effect (like dispel or cure)
|
||||
std::set<ui32> resistedCres; // creatures that resisted the spell (e.g. Dwarves)
|
||||
std::set<ui32> reflectedCres; // creatures that reflected the spell (e.g. Magic Mirror spell)
|
||||
si32 casterStack;// -1 if not cated by creature, >=0 caster stack ID
|
||||
bool castByHero; //if true - spell has been cast by hero, otherwise by a creature
|
||||
|
||||
@ -1748,8 +1744,9 @@ struct BattleSpellCast : public CPackForClient
|
||||
h & spellID;
|
||||
h & manaGained;
|
||||
h & tile;
|
||||
h & customEffects;
|
||||
h & affectedCres;
|
||||
h & resistedCres;
|
||||
h & reflectedCres;
|
||||
h & casterStack;
|
||||
h & castByHero;
|
||||
h & activeCast;
|
||||
|
@ -250,27 +250,6 @@ struct ArtifactLocation
|
||||
}
|
||||
};
|
||||
|
||||
///custom effect (resistance, reflection, etc)
|
||||
struct CustomEffectInfo
|
||||
{
|
||||
CustomEffectInfo()
|
||||
:effect(0),
|
||||
sound(0),
|
||||
stack(0)
|
||||
{
|
||||
}
|
||||
/// WoG AC format
|
||||
ui32 effect;
|
||||
ui32 sound;
|
||||
ui32 stack;
|
||||
template <typename Handler> void serialize(Handler & h, const int version)
|
||||
{
|
||||
h & effect;
|
||||
h & sound;
|
||||
h & stack;
|
||||
}
|
||||
};
|
||||
|
||||
class EntityChanges
|
||||
{
|
||||
public:
|
||||
|
@ -401,12 +401,12 @@ void BattleSpellMechanics::beforeCast(BattleSpellCast & sc, vstd::RNG & rng, con
|
||||
{
|
||||
if(caster->getCasterUnitId() >= 0)
|
||||
{
|
||||
addCustomEffect(sc, caster->getCasterUnitId(), 3);
|
||||
sc.reflectedCres.insert(caster->getCasterUnitId());
|
||||
}
|
||||
}
|
||||
|
||||
for(auto unit : resisted)
|
||||
addCustomEffect(sc, unit, 78);
|
||||
sc.resistedCres.insert(unit->unitId());
|
||||
}
|
||||
|
||||
void BattleSpellMechanics::castEval(ServerCallback * server, const Target & target)
|
||||
@ -430,19 +430,6 @@ void BattleSpellMechanics::castEval(ServerCallback * server, const Target & targ
|
||||
p.first->apply(server, this, p.second);
|
||||
}
|
||||
|
||||
void BattleSpellMechanics::addCustomEffect(BattleSpellCast & sc, const battle::Unit * target, ui32 effect)
|
||||
{
|
||||
addCustomEffect(sc, target->unitId(), effect);
|
||||
}
|
||||
|
||||
void BattleSpellMechanics::addCustomEffect(BattleSpellCast & sc, ui32 targetId, ui32 effect)
|
||||
{
|
||||
CustomEffectInfo customEffect;
|
||||
customEffect.effect = effect;
|
||||
customEffect.stack = targetId;
|
||||
sc.customEffects.push_back(customEffect);
|
||||
}
|
||||
|
||||
std::set<const battle::Unit *> BattleSpellMechanics::collectTargets() const
|
||||
{
|
||||
std::set<const battle::Unit *> result;
|
||||
|
@ -57,9 +57,6 @@ private:
|
||||
|
||||
void beforeCast(BattleSpellCast & sc, vstd::RNG & rng, const Target & target);
|
||||
|
||||
void addCustomEffect(BattleSpellCast & sc, const battle::Unit * target, ui32 effect);
|
||||
void addCustomEffect(BattleSpellCast & sc, ui32 targetId, ui32 effect);
|
||||
|
||||
std::set<const battle::Unit *> collectTargets() const;
|
||||
|
||||
static void doRemoveEffects(ServerCallback * server, const std::vector<const battle::Unit *> & targets, const CSelector & selector);
|
||||
|
@ -33,7 +33,6 @@ VCMI_REGISTER_SPELL_EFFECT(Damage, EFFECT_NAME);
|
||||
|
||||
Damage::Damage()
|
||||
: UnitEffect(),
|
||||
customEffectId(-1),
|
||||
killByPercentage(false),
|
||||
killByCount(false)
|
||||
{
|
||||
@ -74,12 +73,6 @@ void Damage::apply(ServerCallback * server, const Mechanics * m, const EffectTar
|
||||
damageToDisplay += bsa.damageAmount;
|
||||
killed += bsa.killedAmount;
|
||||
}
|
||||
if(customEffectId >= 0)
|
||||
{
|
||||
bsa.effect = 82;
|
||||
bsa.flags |= BattleStackAttacked::EFFECT;
|
||||
}
|
||||
|
||||
stacksInjured.stacks.push_back(bsa);
|
||||
}
|
||||
targetIndex++;
|
||||
@ -116,7 +109,6 @@ bool Damage::isReceptive(const Mechanics * m, const battle::Unit * unit) const
|
||||
|
||||
void Damage::serializeJsonUnitEffect(JsonSerializeFormat & handler)
|
||||
{
|
||||
handler.serializeInt("customEffectId", customEffectId, -1);
|
||||
handler.serializeBool("killByPercentage", killByPercentage);
|
||||
handler.serializeBool("killByCount", killByCount);
|
||||
}
|
||||
|
@ -39,7 +39,6 @@ protected:
|
||||
virtual void describeEffect(std::vector<MetaString> & log, const Mechanics * m, const battle::Unit * firstTarget, uint32_t kills, int64_t damage, bool multiple) const;
|
||||
|
||||
private:
|
||||
int32_t customEffectId;
|
||||
bool killByPercentage;
|
||||
bool killByCount;
|
||||
};
|
||||
|
@ -1182,10 +1182,9 @@ void CGameHandler::makeAttack(const CStack * attacker, const CStack * defender,
|
||||
|
||||
BattleStackAttacked bsa;
|
||||
|
||||
bsa.flags |= BattleStackAttacked::FIRE_SHIELD;
|
||||
bsa.stackAttacked = attacker->ID; //invert
|
||||
bsa.attackerID = uint32_t(-1);
|
||||
bsa.flags |= BattleStackAttacked::EFFECT;
|
||||
bsa.effect = 11;
|
||||
bsa.attackerID = defender->ID;
|
||||
bsa.damageAmount = totalDamage;
|
||||
attacker->prepareAttacked(bsa, getRandomGenerator());
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user