diff options
author | trickerer <onlysuffering@gmail.com> | 2013-12-05 14:33:07 +0700 |
---|---|---|
committer | trickerer <onlysuffering@gmail.com> | 2013-12-05 14:33:07 +0700 |
commit | e536369ce8e15b6798042b0061e8d02663a42795 (patch) | |
tree | 1c8712b66ed9a6f620bdbf36a1d9279b71825acc /src | |
parent | 6e69db25b7162d7c58c50b9cd3f4693d7bda7a5f (diff) |
Multiple spell reflection
Diffstat (limited to 'src')
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 13 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 33 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 19 |
3 files changed, 63 insertions, 2 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index 54db2da73df..ec1bdbda405 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -14264,7 +14264,18 @@ void Unit::ProcDamageAndSpellFor(bool isVictim, Unit* target, uint32 procFlag, u // Remove charge (aura can be removed by triggers) if (prepare && useCharges && takeCharges) - i->aura->DropCharge(); + { + // Set charge drop delay (only for missiles) + if ((procExtra & PROC_EX_REFLECT) && target && procSpell && procSpell->Speed > 0.0f) + { + // Set up missile speed based delay (from Spell.cpp: Spell::AddUnitTarget()::L2237) + uint32 delay = uint32(floor(std::max<float>(target->GetDistance(this), 5.0f) / procSpell->Speed * 1000.0f)); + // Schedule charge drop + i->aura->DropChargeDelayed(delay); + } + else + i->aura->DropCharge(); + } i->aura->CallScriptAfterProcHandlers(aurApp, eventInfo); diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp index efacdd151db..cdc8a3a231d 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -345,6 +345,7 @@ m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false) m_procCharges = CalcMaxCharges(caster); m_isUsingCharges = m_procCharges != 0; // m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs + m_dropEvent = NULL; } AuraScript* Aura::GetScriptByName(std::string const& scriptName) const @@ -466,6 +467,12 @@ void Aura::_Remove(AuraRemoveMode removeMode) target->_UnapplyAura(aurApp, removeMode); appItr = m_applications.begin(); } + + if (m_dropEvent) + { + m_dropEvent->to_Abort = true; + m_dropEvent = NULL; + } } void Aura::UpdateTargetMap(Unit* caster, bool apply) @@ -806,6 +813,26 @@ bool Aura::ModCharges(int32 num, AuraRemoveMode removeMode) return false; } +void Aura::ModChargesDelayed(int32 num, AuraRemoveMode removeMode) +{ + m_dropEvent = NULL; + ModCharges(num, removeMode); +} + +void Aura::DropChargeDelayed(uint32 delay, AuraRemoveMode removeMode) +{ + // aura is already during delayed charge drop + if (m_dropEvent) + return; + // only units have events + Unit* owner = m_owner->ToUnit(); + if (!owner) + return; + + m_dropEvent = new ChargeDropEvent(this, removeMode); + owner->m_Events.AddEvent(m_dropEvent, owner->m_Events.CalculateTime(delay)); +} + void Aura::SetStackAmount(uint8 stackAmount) { m_stackAmount = stackAmount; @@ -2487,3 +2514,9 @@ void DynObjAura::FillTargetMap(std::map<Unit*, uint8> & targets, Unit* /*caster* } } +bool ChargeDropEvent::Execute(uint64 /*e_time*/, uint32 /*p_time*/) +{ + // _base is always valid (look in Aura::_Remove()) + _base->ModChargesDelayed(-1, _mode); + return true; +} diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h index 9e7d0cce82c..704581e925a 100644 --- a/src/server/game/Spells/Auras/SpellAuras.h +++ b/src/server/game/Spells/Auras/SpellAuras.h @@ -34,6 +34,7 @@ class Aura; class DynamicObject; class AuraScript; class ProcInfo; +class ChargeDropEvent; // update aura target map every 500 ms instead of every update - reduce amount of grid searcher calls #define UPDATE_TARGET_MAP_INTERVAL 500 @@ -131,7 +132,7 @@ class Aura void SetDuration(int32 duration, bool withMods = false); void RefreshDuration(); void RefreshTimers(); - bool IsExpired() const { return !GetDuration();} + bool IsExpired() const { return !GetDuration() && !m_dropEvent; } bool IsPermanent() const { return GetMaxDuration() == -1; } uint8 GetCharges() const { return m_procCharges; } @@ -140,6 +141,8 @@ class Aura uint8 CalcMaxCharges() const { return CalcMaxCharges(GetCaster()); } bool ModCharges(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); bool DropCharge(AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT) { return ModCharges(-1, removeMode); } + void ModChargesDelayed(int32 num, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); + void DropChargeDelayed(uint32 delay, AuraRemoveMode removeMode = AURA_REMOVE_BY_DEFAULT); uint8 GetStackAmount() const { return m_stackAmount; } void SetStackAmount(uint8 num); @@ -262,6 +265,8 @@ class Aura bool m_isSingleTarget:1; // true if it's a single target spell and registered at caster - can change at spell steal for example bool m_isUsingCharges:1; + ChargeDropEvent* m_dropEvent; + private: Unit::AuraApplicationList m_removedApplications; }; @@ -297,4 +302,16 @@ class DynObjAura : public Aura void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster); }; + +class ChargeDropEvent : public BasicEvent +{ + friend class Aura; + protected: + ChargeDropEvent(Aura* base, AuraRemoveMode mode) : _base(base), _mode(mode) { } + bool Execute(uint64 /*e_time*/, uint32 /*p_time*/); + + private: + Aura* _base; + AuraRemoveMode _mode; +}; #endif |