aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authortrickerer <onlysuffering@gmail.com>2013-12-05 14:33:07 +0700
committertrickerer <onlysuffering@gmail.com>2013-12-05 14:33:07 +0700
commite536369ce8e15b6798042b0061e8d02663a42795 (patch)
tree1c8712b66ed9a6f620bdbf36a1d9279b71825acc /src
parent6e69db25b7162d7c58c50b9cd3f4693d7bda7a5f (diff)
Multiple spell reflection
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp13
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp33
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h19
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