diff options
author | jackpoz <giacomopoz@gmail.com> | 2014-08-25 19:59:19 +0200 |
---|---|---|
committer | jackpoz <giacomopoz@gmail.com> | 2014-08-25 19:59:19 +0200 |
commit | 10b7480e70a77442a263ec5e358adf2146f348fe (patch) | |
tree | da4bb8816f94fc0fbc0c5a33308af1bdc6510043 | |
parent | 16f3e6597d82b879408678f799932abff93c781f (diff) | |
parent | e536369ce8e15b6798042b0061e8d02663a42795 (diff) |
Merge branch 'trickerer/mulreflect' into master
Close pull request #11288
-rw-r--r-- | src/server/game/Entities/Unit/Unit.cpp | 13 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.cpp | 34 | ||||
-rw-r--r-- | src/server/game/Spells/Auras/SpellAuras.h | 19 |
3 files changed, 63 insertions, 3 deletions
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp index d75e7db11fe..bfa57ef64b8 100644 --- a/src/server/game/Entities/Unit/Unit.cpp +++ b/src/server/game/Entities/Unit/Unit.cpp @@ -14333,7 +14333,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(std::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 348869075ee..07cfa80f297 100644 --- a/src/server/game/Spells/Auras/SpellAuras.cpp +++ b/src/server/game/Spells/Auras/SpellAuras.cpp @@ -335,7 +335,7 @@ m_spellInfo(spellproto), m_casterGuid(casterGUID ? casterGUID : caster->GetGUID( m_castItemGuid(castItem ? castItem->GetGUID() : 0), m_applyTime(time(NULL)), m_owner(owner), m_timeCla(0), m_updateTargetMapInterval(0), m_casterLevel(caster ? caster->getLevel() : m_spellInfo->SpellLevel), m_procCharges(0), m_stackAmount(1), -m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false) +m_isRemoved(false), m_isSingleTarget(false), m_isUsingCharges(false), m_dropEvent(nullptr) { if (m_spellInfo->ManaPerSecond || m_spellInfo->ManaPerSecondPerLevel) m_timeCla = 1 * IN_MILLISECONDS; @@ -467,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 = nullptr; + } } void Aura::UpdateTargetMap(Unit* caster, bool apply) @@ -815,6 +821,26 @@ bool Aura::ModCharges(int32 num, AuraRemoveMode removeMode) return false; } +void Aura::ModChargesDelayed(int32 num, AuraRemoveMode removeMode) +{ + m_dropEvent = nullptr; + 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; @@ -2538,3 +2564,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 e578c0ffc3a..1266bf5c6ec 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(bool withMods = false); 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); @@ -264,6 +267,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; }; @@ -299,4 +304,16 @@ class DynObjAura : public Aura void FillTargetMap(std::map<Unit*, uint8> & targets, Unit* caster) override; }; + +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 |