[Spells]Heartbeat resist first implementation
This commit is contained in:
parent
1eb0c33e69
commit
0e963b4555
@ -4861,6 +4861,13 @@ void Aura::HandleInterruptRegen(bool apply, bool Real)
|
||||
GetTarget()->SetInDummyCombatState(apply);
|
||||
}
|
||||
|
||||
// NOTE this may be moved to the header file, but no need because it is used locally
|
||||
#define HEARTBEAT_AURA_MECHANIC_MASK ( \
|
||||
(1 << (MECHANIC_CHARM - 1)) | (1 << (MECHANIC_BANISH - 1)) | (1 << (MECHANIC_DISORIENTED - 1)) | \
|
||||
(1 << (MECHANIC_POLYMORPH - 1)) | (1 << (MECHANIC_HORROR - 1)) | (1 << (MECHANIC_FEAR - 1)) | \
|
||||
(1 << (MECHANIC_SLEEP - 1)) | (1 << (MECHANIC_SAPPED - 1)) | (1 << (MECHANIC_FREEZE - 1)) | \
|
||||
(1 << (MECHANIC_ROOT - 1)) | (1 << (MECHANIC_STUN - 1)) | (1 << (MECHANIC_KNOCKOUT - 1)))
|
||||
|
||||
SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit* target, WorldObject* caster, Item* castItem) :
|
||||
m_spellProto(spellproto),
|
||||
m_target(target), m_castItemGuid(castItem ? castItem->GetObjectGuid() : ObjectGuid()),
|
||||
@ -4917,6 +4924,9 @@ SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit* target, Wor
|
||||
break;
|
||||
}
|
||||
|
||||
m_isHeartbeatSubject = (GetSpellMechanicMask(m_spellProto, (1 << MAX_EFFECT_INDEX) - 1) & HEARTBEAT_AURA_MECHANIC_MASK)
|
||||
&& caster->GetTypeId() == TYPEID_PLAYER && target->GetTypeId() == TYPEID_PLAYER && !IsChanneledSpell(m_spellProto);
|
||||
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{ m_auras[i] = NULL; }
|
||||
}
|
||||
@ -5436,6 +5446,18 @@ void SpellAuraHolder::Update(uint32 diff)
|
||||
if (Aura* aura = m_auras[i])
|
||||
{ aura->UpdateAura(diff); }
|
||||
|
||||
if (m_isHeartbeatSubject && m_duration)
|
||||
{
|
||||
if (HeartbeatResist(diff)) //m_duration, GetCaster()->ToPlayer(), GetTarget()->ToPlayer() all available within AuraHolder instance
|
||||
{
|
||||
if (diff >= 1 * IN_MILLISECONDS || urand(1, 1 * IN_MILLISECONDS) < diff)
|
||||
{
|
||||
sLog.outError("Heartbeat: spell %u max timed %u, elapsed %u, chance to resist %f", m_spellProto->Id, m_maxDuration, m_maxDuration - m_duration, pow((m_maxDuration - m_duration + diff) / 15.0f, 2) / (IN_MILLISECONDS*IN_MILLISECONDS));
|
||||
m_duration = 1; //equivalent to remove by expire
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Channeled aura required check distance from caster
|
||||
if (IsChanneledSpell(m_spellProto) && GetCasterGuid() != m_target->GetObjectGuid())
|
||||
{
|
||||
@ -5616,6 +5638,14 @@ void SpellAuraHolder::UpdateAuraDuration()
|
||||
{ SendAuraDurationForCaster((Player*)caster); }
|
||||
}
|
||||
|
||||
bool SpellAuraHolder::HeartbeatResist(uint32 diff)
|
||||
{
|
||||
// m_maxDuration - m_duration : Elapsed aura time in ms
|
||||
// 15 sec is an empirical constant
|
||||
// TODO use target resistances! the simplest formula from valkyrie-wow is used now
|
||||
return (urand(0, IN_MILLISECONDS*IN_MILLISECONDS) < pow((m_maxDuration - m_duration + diff) / 15.0f, 2));
|
||||
}
|
||||
|
||||
void SpellAuraHolder::SendAuraDurationForCaster(Player* caster)
|
||||
{
|
||||
// [-ZERO] Feature doesn't exist in 1.x.
|
||||
|
@ -213,6 +213,7 @@ class SpellAuraHolder
|
||||
~SpellAuraHolder();
|
||||
private:
|
||||
void UpdateAuraApplication(); // called at charges or stack changes
|
||||
bool HeartbeatResist(uint32 diff);
|
||||
|
||||
SpellEntry const* m_spellProto;
|
||||
|
||||
@ -237,6 +238,7 @@ class SpellAuraHolder
|
||||
bool m_isPassive: 1;
|
||||
bool m_isDeathPersist: 1;
|
||||
bool m_isRemovedOnShapeLost: 1;
|
||||
bool m_isHeartbeatSubject: 1;
|
||||
bool m_deleted: 1;
|
||||
|
||||
uint32 m_in_use; // > 0 while in SpellAuraHolder::ApplyModifiers call/SpellAuraHolder::Update/etc
|
||||
|
Loading…
x
Reference in New Issue
Block a user