aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorjackpoz <giacomopoz@gmail.com>2014-08-25 19:59:19 +0200
committerjackpoz <giacomopoz@gmail.com>2014-08-25 19:59:19 +0200
commit10b7480e70a77442a263ec5e358adf2146f348fe (patch)
treeda4bb8816f94fc0fbc0c5a33308af1bdc6510043
parent16f3e6597d82b879408678f799932abff93c781f (diff)
parente536369ce8e15b6798042b0061e8d02663a42795 (diff)
Merge branch 'trickerer/mulreflect' into master
Close pull request #11288
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp13
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp34
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h19
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