Core/Spells: rework part 3: spells only handle at most one UnitAura and one DynObjAura during its lifetime
Port From (https://github.com/TrinityCore/TrinityCore/commit/f3548d45d0a74203ef6f5c7282c31ba794ddf7a1)
This commit is contained in:
@@ -89,7 +89,10 @@ namespace Game.Chat
|
|||||||
if (spellInfo != null)
|
if (spellInfo != null)
|
||||||
{
|
{
|
||||||
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, target.GetMapId(), spellId, target.GetMap().GenerateLowGuid(HighGuid.Cast));
|
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, target.GetMapId(), spellId, target.GetMap().GenerateLowGuid(HighGuid.Cast));
|
||||||
Aura.TryRefreshStackOrCreate(spellInfo, castId, SpellConst.MaxEffectMask, target, target, target.GetMap().GetDifficultyID());
|
AuraCreateInfo createInfo = new(castId, spellInfo, target.GetMap().GetDifficultyID(), SpellConst.MaxEffectMask, target);
|
||||||
|
createInfo.SetCaster(target);
|
||||||
|
|
||||||
|
Aura.TryRefreshStackOrCreate(createInfo);
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
|
|||||||
@@ -910,7 +910,12 @@ namespace Game.Entities
|
|||||||
|
|
||||||
var info = effectInfo[key];
|
var info = effectInfo[key];
|
||||||
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellInfo.Id, GetMap().GenerateLowGuid(HighGuid.Cast));
|
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellInfo.Id, GetMap().GenerateLowGuid(HighGuid.Cast));
|
||||||
Aura aura = Aura.TryCreate(spellInfo, castId, key.EffectMask, this, null, difficulty, info.BaseAmounts, null, casterGuid);
|
|
||||||
|
AuraCreateInfo createInfo = new(castId, spellInfo, difficulty, key.EffectMask, this);
|
||||||
|
createInfo.SetCasterGUID(casterGuid);
|
||||||
|
createInfo.SetBaseAmount(info.BaseAmounts);
|
||||||
|
|
||||||
|
Aura aura = Aura.TryCreate(createInfo);
|
||||||
if (aura != null)
|
if (aura != null)
|
||||||
{
|
{
|
||||||
if (!aura.CanBeSaved())
|
if (!aura.CanBeSaved())
|
||||||
|
|||||||
@@ -542,7 +542,13 @@ namespace Game.Entities
|
|||||||
|
|
||||||
AuraLoadEffectInfo info = effectInfo[key];
|
AuraLoadEffectInfo info = effectInfo[key];
|
||||||
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellInfo.Id, GetMap().GenerateLowGuid(HighGuid.Cast));
|
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellInfo.Id, GetMap().GenerateLowGuid(HighGuid.Cast));
|
||||||
Aura aura = Aura.TryCreate(spellInfo, castId, key.EffectMask, this, null, difficulty, info.BaseAmounts, null, casterGuid, itemGuid, castItemId, castItemLevel);
|
|
||||||
|
AuraCreateInfo createInfo = new(castId, spellInfo, difficulty, key.EffectMask, this);
|
||||||
|
createInfo.SetCasterGUID(casterGuid);
|
||||||
|
createInfo.SetBaseAmount(info.BaseAmounts);
|
||||||
|
createInfo.SetCastItem(itemGuid, castItemId, castItemLevel);
|
||||||
|
|
||||||
|
Aura aura = Aura.TryCreate(createInfo);
|
||||||
if (aura != null)
|
if (aura != null)
|
||||||
{
|
{
|
||||||
if (!aura.CanBeSaved())
|
if (!aura.CanBeSaved())
|
||||||
|
|||||||
@@ -2885,8 +2885,15 @@ namespace Game.Entities
|
|||||||
effMask &= ~(uint)(1 << i);
|
effMask &= ~(uint)(1 << i);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (effMask == 0)
|
||||||
|
return null;
|
||||||
|
|
||||||
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellInfo.Id, GetMap().GenerateLowGuid(HighGuid.Cast));
|
ObjectGuid castId = ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellInfo.Id, GetMap().GenerateLowGuid(HighGuid.Cast));
|
||||||
Aura aura = Aura.TryRefreshStackOrCreate(spellInfo, castId, effMask, target, this, GetMap().GetDifficultyID());
|
|
||||||
|
AuraCreateInfo createInfo = new(castId, spellInfo, GetMap().GetDifficultyID(), effMask, target);
|
||||||
|
createInfo.SetCaster(this);
|
||||||
|
|
||||||
|
Aura aura = Aura.TryRefreshStackOrCreate(createInfo);
|
||||||
if (aura != null)
|
if (aura != null)
|
||||||
{
|
{
|
||||||
aura.ApplyForTargets();
|
aura.ApplyForTargets();
|
||||||
@@ -2952,15 +2959,21 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
else // This can happen during Player._LoadAuras
|
else // This can happen during Player._LoadAuras
|
||||||
{
|
{
|
||||||
int[] bp0 = new int[SpellConst.MaxEffects];
|
int[] bp = new int[SpellConst.MaxEffects];
|
||||||
foreach (SpellEffectInfo effect in spellEntry.GetEffects())
|
foreach (SpellEffectInfo effect in spellEntry.GetEffects())
|
||||||
{
|
{
|
||||||
if (effect != null)
|
if (effect != null)
|
||||||
bp0[effect.EffectIndex] = effect.BasePoints;
|
bp[effect.EffectIndex] = effect.BasePoints;
|
||||||
}
|
}
|
||||||
|
|
||||||
bp0[i] = seatId;
|
bp[i] = seatId;
|
||||||
Aura.TryRefreshStackOrCreate(spellEntry, ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellEntry.Id, GetMap().GenerateLowGuid(HighGuid.Cast)), SpellConst.MaxEffectMask, this, clicker, GetMap().GetDifficultyID(), bp0, null, origCasterGUID);
|
|
||||||
|
AuraCreateInfo createInfo = new(ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellEntry.Id, GetMap().GenerateLowGuid(HighGuid.Cast)), spellEntry, GetMap().GetDifficultyID(), SpellConst.MaxEffectMask, this);
|
||||||
|
createInfo.SetCaster(clicker);
|
||||||
|
createInfo.SetBaseAmount(bp);
|
||||||
|
createInfo.SetCasterGUID(origCasterGUID);
|
||||||
|
|
||||||
|
Aura.TryRefreshStackOrCreate(createInfo);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -2968,7 +2981,13 @@ namespace Game.Entities
|
|||||||
if (IsInMap(caster))
|
if (IsInMap(caster))
|
||||||
caster.CastSpell(target, spellEntry.Id, new CastSpellExtraArgs().SetOriginalCaster(origCasterGUID));
|
caster.CastSpell(target, spellEntry.Id, new CastSpellExtraArgs().SetOriginalCaster(origCasterGUID));
|
||||||
else
|
else
|
||||||
Aura.TryRefreshStackOrCreate(spellEntry, ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellEntry.Id, GetMap().GenerateLowGuid(HighGuid.Cast)), SpellConst.MaxEffectMask, this, clicker, GetMap().GetDifficultyID(), null, null, origCasterGUID);
|
{
|
||||||
|
AuraCreateInfo createInfo = new(ObjectGuid.Create(HighGuid.Cast, SpellCastSource.Normal, GetMapId(), spellEntry.Id, GetMap().GenerateLowGuid(HighGuid.Cast)), spellEntry, GetMap().GetDifficultyID(), SpellConst.MaxEffectMask, this);
|
||||||
|
createInfo.SetCaster(clicker);
|
||||||
|
createInfo.SetCasterGUID(origCasterGUID);
|
||||||
|
|
||||||
|
Aura.TryRefreshStackOrCreate(createInfo);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
spellClickHandled = true;
|
spellClickHandled = true;
|
||||||
@@ -3340,7 +3359,11 @@ namespace Game.Entities
|
|||||||
if (aura.IsSingleTarget())
|
if (aura.IsSingleTarget())
|
||||||
aura.UnregisterSingleTarget();
|
aura.UnregisterSingleTarget();
|
||||||
|
|
||||||
Aura newAura = Aura.TryRefreshStackOrCreate(aura.GetSpellInfo(), aura.GetCastGUID(), effMask, stealer, null, aura.GetCastDifficulty(), baseDamage, null, aura.GetCasterGUID());
|
AuraCreateInfo createInfo = new(aura.GetCastGUID(), aura.GetSpellInfo(), aura.GetCastDifficulty(), effMask, stealer);
|
||||||
|
createInfo.SetCasterGUID(aura.GetCasterGUID());
|
||||||
|
createInfo.SetBaseAmount(baseDamage);
|
||||||
|
|
||||||
|
Aura newAura = Aura.TryRefreshStackOrCreate(createInfo);
|
||||||
if (newAura != null)
|
if (newAura != null)
|
||||||
{
|
{
|
||||||
// created aura must not be single target aura, so stealer won't loose it on recast
|
// created aura must not be single target aura, so stealer won't loose it on recast
|
||||||
@@ -3431,7 +3454,7 @@ namespace Game.Entities
|
|||||||
aura.Remove();
|
aura.Remove();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// All aura base removes should go threw this function!
|
// All aura base removes should go through this function!
|
||||||
public void RemoveOwnedAura(KeyValuePair<uint, Aura> keyValuePair, AuraRemoveMode removeMode = AuraRemoveMode.Default)
|
public void RemoveOwnedAura(KeyValuePair<uint, Aura> keyValuePair, AuraRemoveMode removeMode = AuraRemoveMode.Default)
|
||||||
{
|
{
|
||||||
Aura aura = keyValuePair.Value;
|
Aura aura = keyValuePair.Value;
|
||||||
@@ -4239,41 +4262,32 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Aura _TryStackingOrRefreshingExistingAura(SpellInfo newAura, uint effMask, Unit caster, int[] baseAmount = null, Item castItem = null, ObjectGuid casterGUID = default, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = default, uint castItemId = 0, int castItemLevel = -1)
|
public Aura _TryStackingOrRefreshingExistingAura(AuraCreateInfo createInfo)
|
||||||
{
|
{
|
||||||
Cypher.Assert(!casterGUID.IsEmpty() || caster);
|
Cypher.Assert(!createInfo.CasterGUID.IsEmpty() || createInfo.Caster);
|
||||||
|
|
||||||
// Check if these can stack anyway
|
// Check if these can stack anyway
|
||||||
if (casterGUID.IsEmpty() && !newAura.IsStackableOnOneSlotWithDifferentCasters())
|
if (createInfo.CasterGUID.IsEmpty() && !createInfo.GetSpellInfo().IsStackableOnOneSlotWithDifferentCasters())
|
||||||
casterGUID = caster.GetGUID();
|
createInfo.CasterGUID = createInfo.Caster.GetGUID();
|
||||||
|
|
||||||
// passive and Incanter's Absorption and auras with different type can stack with themselves any number of times
|
// passive and Incanter's Absorption and auras with different type can stack with themselves any number of times
|
||||||
if (!newAura.IsMultiSlotAura())
|
if (!createInfo.GetSpellInfo().IsMultiSlotAura())
|
||||||
{
|
{
|
||||||
// check if cast item changed
|
// check if cast item changed
|
||||||
if (castItem != null)
|
ObjectGuid castItemGUID = createInfo.CastItemGUID;
|
||||||
{
|
|
||||||
castItemGuid = castItem.GetGUID();
|
|
||||||
castItemId = castItem.GetEntry();
|
|
||||||
Player owner = castItem.GetOwner();
|
|
||||||
if (owner)
|
|
||||||
castItemLevel = (int)castItem.GetItemLevel(owner);
|
|
||||||
else if (castItem.GetOwnerGUID() == caster.GetGUID())
|
|
||||||
castItemLevel = (int)castItem.GetItemLevel(caster.ToPlayer());
|
|
||||||
}
|
|
||||||
|
|
||||||
// find current aura from spell and change it's stackamount, or refresh it's duration
|
// find current aura from spell and change it's stackamount, or refresh it's duration
|
||||||
Aura foundAura = GetOwnedAura(newAura.Id, casterGUID, (newAura.HasAttribute(SpellCustomAttributes.EnchantProc) ? castItemGuid : ObjectGuid.Empty), 0);
|
Aura foundAura = GetOwnedAura(createInfo.GetSpellInfo().Id, createInfo.CasterGUID, createInfo.GetSpellInfo().HasAttribute(SpellCustomAttributes.EnchantProc) ? castItemGUID : ObjectGuid.Empty, 0);
|
||||||
if (foundAura != null)
|
if (foundAura != null)
|
||||||
{
|
{
|
||||||
// effect masks do not match
|
// effect masks do not match
|
||||||
// extremely rare case
|
// extremely rare case
|
||||||
// let's just recreate aura
|
// let's just recreate aura
|
||||||
if (effMask != foundAura.GetEffectMask())
|
if (createInfo.GetAuraEffectMask() != foundAura.GetEffectMask())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
// update basepoints with new values - effect amount will be recalculated in ModStackAmount
|
// update basepoints with new values - effect amount will be recalculated in ModStackAmount
|
||||||
foreach (SpellEffectInfo effect in newAura.GetEffects())
|
foreach (SpellEffectInfo effect in createInfo.GetSpellInfo().GetEffects())
|
||||||
{
|
{
|
||||||
if (effect == null)
|
if (effect == null)
|
||||||
continue;
|
continue;
|
||||||
@@ -4283,8 +4297,8 @@ namespace Game.Entities
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
int bp;
|
int bp;
|
||||||
if (baseAmount != null)
|
if (createInfo.BaseAmount != null)
|
||||||
bp = baseAmount[effect.EffectIndex];
|
bp = createInfo.BaseAmount[effect.EffectIndex];
|
||||||
else
|
else
|
||||||
bp = effect.BasePoints;
|
bp = effect.BasePoints;
|
||||||
|
|
||||||
@@ -4292,15 +4306,15 @@ namespace Game.Entities
|
|||||||
}
|
}
|
||||||
|
|
||||||
// correct cast item guid if needed
|
// correct cast item guid if needed
|
||||||
if (castItemGuid != foundAura.GetCastItemGUID())
|
if (castItemGUID != foundAura.GetCastItemGUID())
|
||||||
{
|
{
|
||||||
foundAura.SetCastItemGUID(castItemGuid);
|
foundAura.SetCastItemGUID(castItemGUID);
|
||||||
foundAura.SetCastItemId(castItemId);
|
foundAura.SetCastItemId(createInfo.CastItemId);
|
||||||
foundAura.SetCastItemLevel(castItemLevel);
|
foundAura.SetCastItemLevel(createInfo.CastItemLevel);
|
||||||
}
|
}
|
||||||
|
|
||||||
// try to increase stack amount
|
// try to increase stack amount
|
||||||
foundAura.ModStackAmount(1, AuraRemoveMode.Default, resetPeriodicTimer);
|
foundAura.ModStackAmount(1, AuraRemoveMode.Default, createInfo.ResetPeriodicTimer);
|
||||||
return foundAura;
|
return foundAura;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -724,18 +724,22 @@ namespace Game.Scripting
|
|||||||
void PreventHitHeal() { SetHitHeal(0); }
|
void PreventHitHeal() { SetHitHeal(0); }
|
||||||
public Spell GetSpell() { return m_spell; }
|
public Spell GetSpell() { return m_spell; }
|
||||||
// returns current spell hit target aura
|
// returns current spell hit target aura
|
||||||
public Aura GetHitAura()
|
public Aura GetHitAura(bool dynObjAura = false)
|
||||||
{
|
{
|
||||||
if (!IsInTargetHook())
|
if (!IsInTargetHook())
|
||||||
{
|
{
|
||||||
Log.outError(LogFilter.Scripts, "Script: `{0}` Spell: `{1}`: function SpellScript.GetHitAura was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId);
|
Log.outError(LogFilter.Scripts, "Script: `{0}` Spell: `{1}`: function SpellScript.GetHitAura was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if (m_spell.m_spellAura == null)
|
|
||||||
|
Aura aura = m_spell.spellAura;
|
||||||
|
if (dynObjAura)
|
||||||
|
aura = m_spell.dynObjAura;
|
||||||
|
|
||||||
|
if (aura == null || aura.IsRemoved())
|
||||||
return null;
|
return null;
|
||||||
if (m_spell.m_spellAura.IsRemoved())
|
|
||||||
return null;
|
return aura;
|
||||||
return m_spell.m_spellAura;
|
|
||||||
}
|
}
|
||||||
// prevents applying aura on current spell hit target
|
// prevents applying aura on current spell hit target
|
||||||
public void PreventHitAura()
|
public void PreventHitAura()
|
||||||
@@ -745,8 +749,14 @@ namespace Game.Scripting
|
|||||||
Log.outError(LogFilter.Scripts, "Script: `{0}` Spell: `{1}`: function SpellScript.PreventHitAura was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId);
|
Log.outError(LogFilter.Scripts, "Script: `{0}` Spell: `{1}`: function SpellScript.PreventHitAura was called, but function has no effect in current hook!", m_scriptName, m_scriptSpellId);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
if (m_spell.m_spellAura != null)
|
|
||||||
m_spell.m_spellAura.Remove();
|
UnitAura unitAura = m_spell.spellAura;
|
||||||
|
if (unitAura != null)
|
||||||
|
unitAura.Remove();
|
||||||
|
|
||||||
|
DynObjAura dynAura = m_spell.dynObjAura;
|
||||||
|
if (dynAura != null)
|
||||||
|
dynAura.Remove();
|
||||||
}
|
}
|
||||||
|
|
||||||
// prevents effect execution on current spell hit target
|
// prevents effect execution on current spell hit target
|
||||||
|
|||||||
+310
-189
@@ -189,6 +189,37 @@ namespace Game.Spells
|
|||||||
SetNeedClientUpdate();
|
SetNeedClientUpdate();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void UpdateApplyEffectMask(uint newEffMask)
|
||||||
|
{
|
||||||
|
if (_effectsToApply == newEffMask)
|
||||||
|
return;
|
||||||
|
|
||||||
|
uint removeEffMask = (_effectsToApply ^ newEffMask) & (~newEffMask);
|
||||||
|
uint addEffMask = (_effectsToApply ^ newEffMask) & (~_effectsToApply);
|
||||||
|
|
||||||
|
// quick check, removes application completely
|
||||||
|
if (removeEffMask == _effectsToApply && addEffMask == 0)
|
||||||
|
{
|
||||||
|
_target._UnapplyAura(this, AuraRemoveMode.Default);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint i = 0; i < SpellConst.MaxEffects; ++i)
|
||||||
|
{
|
||||||
|
// update real effects only if they were applied already
|
||||||
|
if ((_effectMask & (1 << (int)i)) == 0)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if ((removeEffMask & (1 << (int)i)) != 0)
|
||||||
|
_HandleEffect(i, false);
|
||||||
|
|
||||||
|
if ((addEffMask & (1 << (int)i)) != 0)
|
||||||
|
_HandleEffect(i, true);
|
||||||
|
}
|
||||||
|
|
||||||
|
_effectsToApply = newEffMask;
|
||||||
|
}
|
||||||
|
|
||||||
public void SetNeedClientUpdate()
|
public void SetNeedClientUpdate()
|
||||||
{
|
{
|
||||||
if (_needClientUpdate || GetRemoveMode() != AuraRemoveMode.None)
|
if (_needClientUpdate || GetRemoveMode() != AuraRemoveMode.None)
|
||||||
@@ -294,21 +325,21 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
const int UPDATE_TARGET_MAP_INTERVAL = 500;
|
const int UPDATE_TARGET_MAP_INTERVAL = 500;
|
||||||
|
|
||||||
public Aura(SpellInfo spellproto, ObjectGuid castId, WorldObject owner, Unit caster, Difficulty castDifficulty, Item castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint castItemId, int castItemLevel)
|
public Aura(AuraCreateInfo createInfo)
|
||||||
{
|
{
|
||||||
m_spellInfo = spellproto;
|
m_spellInfo = createInfo._spellInfo;
|
||||||
m_castDifficulty = castDifficulty;
|
m_castDifficulty = createInfo._castDifficulty;
|
||||||
m_castGuid = castId;
|
m_castGuid = createInfo._castId;
|
||||||
m_casterGuid = !casterGUID.IsEmpty() ? casterGUID : caster.GetGUID();
|
m_casterGuid = createInfo.CasterGUID.IsEmpty() ? createInfo.Caster.GetGUID() : createInfo.CasterGUID;
|
||||||
m_castItemGuid = castItem != null ? castItem.GetGUID() : castItemGuid;
|
m_castItemGuid = createInfo.CastItemGUID;
|
||||||
m_castItemId = castItem != null ? castItem.GetEntry() : castItemId;
|
m_castItemId = createInfo.CastItemId;
|
||||||
m_castItemLevel = castItemLevel;
|
m_castItemLevel = createInfo.CastItemLevel;
|
||||||
m_spellVisual = new SpellCastVisual(caster ? caster.GetCastSpellXSpellVisualId(spellproto) : spellproto.GetSpellXSpellVisualId(), 0);
|
m_spellVisual = new SpellCastVisual(createInfo.Caster ? createInfo.Caster.GetCastSpellXSpellVisualId(createInfo._spellInfo) : createInfo._spellInfo.GetSpellXSpellVisualId(), 0);
|
||||||
m_applyTime = GameTime.GetGameTime();
|
m_applyTime = GameTime.GetGameTime();
|
||||||
m_owner = owner;
|
m_owner = createInfo._owner;
|
||||||
m_timeCla = 0;
|
m_timeCla = 0;
|
||||||
m_updateTargetMapInterval = 0;
|
m_updateTargetMapInterval = 0;
|
||||||
m_casterLevel = caster != null ? caster.GetLevel() : m_spellInfo.SpellLevel;
|
m_casterLevel = createInfo.Caster ? createInfo.Caster.GetLevel() : m_spellInfo.SpellLevel;
|
||||||
m_procCharges = 0;
|
m_procCharges = 0;
|
||||||
m_stackAmount = 1;
|
m_stackAmount = 1;
|
||||||
m_isRemoved = false;
|
m_isRemoved = false;
|
||||||
@@ -324,9 +355,9 @@ namespace Game.Spells
|
|||||||
if (!m_periodicCosts.Empty())
|
if (!m_periodicCosts.Empty())
|
||||||
m_timeCla = 1 * Time.InMilliseconds;
|
m_timeCla = 1 * Time.InMilliseconds;
|
||||||
|
|
||||||
m_maxDuration = CalcMaxDuration(caster);
|
m_maxDuration = CalcMaxDuration(createInfo.Caster);
|
||||||
m_duration = m_maxDuration;
|
m_duration = m_maxDuration;
|
||||||
m_procCharges = CalcMaxCharges(caster);
|
m_procCharges = CalcMaxCharges(createInfo.Caster);
|
||||||
m_isUsingCharges = m_procCharges != 0;
|
m_isUsingCharges = m_procCharges != 0;
|
||||||
// m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
|
// m_casterLevel = cast item level/caster level, caster level should be saved to db, confirmed with sniffs
|
||||||
}
|
}
|
||||||
@@ -411,7 +442,7 @@ namespace Game.Spells
|
|||||||
Cypher.Assert(app == auraApp);
|
Cypher.Assert(app == auraApp);
|
||||||
m_applications.Remove(target.GetGUID());
|
m_applications.Remove(target.GetGUID());
|
||||||
|
|
||||||
m_removedApplications.Add(auraApp);
|
_removedApplications.Add(auraApp);
|
||||||
|
|
||||||
// reset cooldown state for spells
|
// reset cooldown state for spells
|
||||||
if (caster != null && GetSpellInfo().IsCooldownStartedOnEvent())
|
if (caster != null && GetSpellInfo().IsCooldownStartedOnEvent())
|
||||||
@@ -465,9 +496,17 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
// needs readding - remove now, will be applied in next update cycle
|
// needs readding - remove now, will be applied in next update cycle
|
||||||
// (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
|
// (dbcs do not have auras which apply on same type of targets but have different radius, so this is not really needed)
|
||||||
if (app.Value.GetEffectMask() != existing.Value || !CanBeAppliedOn(existing.Key))
|
if (!CanBeAppliedOn(existing.Key))
|
||||||
|
{
|
||||||
targetsToRemove.Add(app.Value.GetTarget());
|
targetsToRemove.Add(app.Value.GetTarget());
|
||||||
// nothing todo - aura already applied
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// needs to add/remove effects from application, don't remove from map so it gets updated
|
||||||
|
if (app.Value.GetEffectMask() != existing.Value)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
// nothing to do - aura already applied
|
||||||
// remove from auras to register list
|
// remove from auras to register list
|
||||||
targets.Remove(existing.Key);
|
targets.Remove(existing.Key);
|
||||||
}
|
}
|
||||||
@@ -475,28 +514,6 @@ namespace Game.Spells
|
|||||||
// register auras for units
|
// register auras for units
|
||||||
foreach (var unit in targets.Keys.ToList())
|
foreach (var unit in targets.Keys.ToList())
|
||||||
{
|
{
|
||||||
// aura mustn't be already applied on target
|
|
||||||
AuraApplication aurApp = GetApplicationOfTarget(unit.GetGUID());
|
|
||||||
if (aurApp != null)
|
|
||||||
{
|
|
||||||
// the core created 2 different units with same guid
|
|
||||||
// this is a major failue, which i can't fix right now
|
|
||||||
// let's remove one unit from aura list
|
|
||||||
// this may cause area aura "bouncing" between 2 units after each update
|
|
||||||
// but because we know the reason of a crash we can remove the assertion for now
|
|
||||||
if (aurApp.GetTarget() != unit)
|
|
||||||
{
|
|
||||||
// remove from auras to register list
|
|
||||||
targets.Remove(unit);
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// ok, we have one unit twice in target map (impossible, but...)
|
|
||||||
Cypher.Assert(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var value = targets[unit];
|
var value = targets[unit];
|
||||||
|
|
||||||
bool addUnit = true;
|
bool addUnit = true;
|
||||||
@@ -506,8 +523,9 @@ namespace Game.Spells
|
|||||||
if (unit.IsImmunedToSpellEffect(GetSpellInfo(), effIndex, caster))
|
if (unit.IsImmunedToSpellEffect(GetSpellInfo(), effIndex, caster))
|
||||||
value &= ~(1u << effIndex);
|
value &= ~(1u << effIndex);
|
||||||
}
|
}
|
||||||
if (value == 0 || unit.IsImmunedToSpell(GetSpellInfo(), caster)
|
|
||||||
|| !CanBeAppliedOn(unit))
|
|
||||||
|
if (value == 0 || unit.IsImmunedToSpell(GetSpellInfo(), caster) || !CanBeAppliedOn(unit))
|
||||||
addUnit = false;
|
addUnit = false;
|
||||||
|
|
||||||
if (addUnit && !unit.IsHighestExclusiveAura(this, true))
|
if (addUnit && !unit.IsHighestExclusiveAura(this, true))
|
||||||
@@ -541,6 +559,7 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!addUnit)
|
if (!addUnit)
|
||||||
targets.Remove(unit);
|
targets.Remove(unit);
|
||||||
else
|
else
|
||||||
@@ -553,6 +572,14 @@ namespace Game.Spells
|
|||||||
m_owner.GetName(), m_owner.IsInWorld ? (int)m_owner.GetMap().GetId() : -1,
|
m_owner.GetName(), m_owner.IsInWorld ? (int)m_owner.GetMap().GetId() : -1,
|
||||||
unit.GetName(), unit.IsInWorld ? (int)unit.GetMap().GetId() : -1);
|
unit.GetName(), unit.IsInWorld ? (int)unit.GetMap().GetId() : -1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
AuraApplication aurApp = GetApplicationOfTarget(unit.GetGUID());
|
||||||
|
if (aurApp != null)
|
||||||
|
{
|
||||||
|
// aura is already applied, this means we need to update effects of current application
|
||||||
|
unit._UnapplyAura(aurApp, AuraRemoveMode.Default);
|
||||||
|
}
|
||||||
|
|
||||||
unit._CreateAuraApplication(this, value);
|
unit._CreateAuraApplication(this, value);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -854,17 +881,17 @@ namespace Game.Spells
|
|||||||
Unit caster = GetCaster();
|
Unit caster = GetCaster();
|
||||||
|
|
||||||
List<AuraApplication> applications = GetApplicationList();
|
List<AuraApplication> applications = GetApplicationList();
|
||||||
foreach (var appt in applications)
|
foreach (var aurApp in applications)
|
||||||
if (!appt.HasRemoveMode())
|
if (!aurApp.HasRemoveMode())
|
||||||
HandleAuraSpecificMods(appt, caster, false, true);
|
HandleAuraSpecificMods(aurApp, caster, false, true);
|
||||||
|
|
||||||
foreach (AuraEffect effect in GetAuraEffects())
|
foreach (AuraEffect aurEff in GetAuraEffects())
|
||||||
if (effect != null)
|
if (aurEff != null)
|
||||||
effect.ChangeAmount(effect.CalculateAmount(caster), false, true);
|
aurEff.ChangeAmount(aurEff.CalculateAmount(caster), false, true);
|
||||||
|
|
||||||
foreach (var app in applications)
|
foreach (var aurApp in applications)
|
||||||
if (!app.HasRemoveMode())
|
if (!aurApp.HasRemoveMode())
|
||||||
HandleAuraSpecificMods(app, caster, true, true);
|
HandleAuraSpecificMods(aurApp, caster, true, true);
|
||||||
|
|
||||||
SetNeedClientUpdateForTargets();
|
SetNeedClientUpdateForTargets();
|
||||||
}
|
}
|
||||||
@@ -956,6 +983,14 @@ namespace Game.Spells
|
|||||||
return GetSpellInfo().IsDeathPersistent();
|
return GetSpellInfo().IsDeathPersistent();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public bool IsRemovedOnShapeLost(Unit target)
|
||||||
|
{
|
||||||
|
return GetCasterGUID() == target.GetGUID()
|
||||||
|
&& m_spellInfo.Stances != 0
|
||||||
|
&& !m_spellInfo.HasAttribute(SpellAttr2.NotNeedShapeshift)
|
||||||
|
&& !m_spellInfo.HasAttribute(SpellAttr0.NotShapeshift);
|
||||||
|
}
|
||||||
|
|
||||||
public bool CanBeSaved()
|
public bool CanBeSaved()
|
||||||
{
|
{
|
||||||
if (IsPassive())
|
if (IsPassive())
|
||||||
@@ -1135,10 +1170,10 @@ namespace Game.Spells
|
|||||||
public List<AuraApplication> GetApplicationList()
|
public List<AuraApplication> GetApplicationList()
|
||||||
{
|
{
|
||||||
var applicationList = new List<AuraApplication>();
|
var applicationList = new List<AuraApplication>();
|
||||||
foreach (var app in m_applications.Values)
|
foreach (var aurApp in m_applications.Values)
|
||||||
{
|
{
|
||||||
if (app.GetEffectMask() != 0)
|
if (aurApp.GetEffectMask() != 0)
|
||||||
applicationList.Add(app);
|
applicationList.Add(aurApp);
|
||||||
}
|
}
|
||||||
|
|
||||||
return applicationList;
|
return applicationList;
|
||||||
@@ -1816,7 +1851,7 @@ namespace Game.Spells
|
|||||||
|
|
||||||
void _DeleteRemovedApplications()
|
void _DeleteRemovedApplications()
|
||||||
{
|
{
|
||||||
m_removedApplications.Clear();
|
_removedApplications.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
public void LoadScripts()
|
public void LoadScripts()
|
||||||
@@ -2308,13 +2343,6 @@ namespace Game.Spells
|
|||||||
public byte GetStackAmount() { return m_stackAmount; }
|
public byte GetStackAmount() { return m_stackAmount; }
|
||||||
public byte GetCasterLevel() { return (byte)m_casterLevel; }
|
public byte GetCasterLevel() { return (byte)m_casterLevel; }
|
||||||
|
|
||||||
public bool IsRemovedOnShapeLost(Unit target)
|
|
||||||
{
|
|
||||||
return GetCasterGUID() == target.GetGUID()
|
|
||||||
&& m_spellInfo.Stances != 0
|
|
||||||
&& !m_spellInfo.HasAttribute(SpellAttr2.NotNeedShapeshift)
|
|
||||||
&& !m_spellInfo.HasAttribute(SpellAttr0.NotShapeshift);
|
|
||||||
}
|
|
||||||
public bool IsRemoved() { return m_isRemoved; }
|
public bool IsRemoved() { return m_isRemoved; }
|
||||||
|
|
||||||
public bool IsSingleTarget() { return m_isSingleTarget; }
|
public bool IsSingleTarget() { return m_isSingleTarget; }
|
||||||
@@ -2334,9 +2362,10 @@ namespace Game.Spells
|
|||||||
public uint GetEffectMask()
|
public uint GetEffectMask()
|
||||||
{
|
{
|
||||||
uint effMask = 0;
|
uint effMask = 0;
|
||||||
foreach (AuraEffect effect in GetAuraEffects())
|
foreach (AuraEffect aurEff in GetAuraEffects())
|
||||||
if (effect != null)
|
if (aurEff != null)
|
||||||
effMask |= (uint)(1 << (int)effect.GetEffIndex());
|
effMask |= (uint)(1 << (int)aurEff.GetEffIndex());
|
||||||
|
|
||||||
return effMask;
|
return effMask;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2354,6 +2383,11 @@ namespace Game.Spells
|
|||||||
public void SetLastProcAttemptTime(DateTime lastProcAttemptTime) { m_lastProcAttemptTime = lastProcAttemptTime; }
|
public void SetLastProcAttemptTime(DateTime lastProcAttemptTime) { m_lastProcAttemptTime = lastProcAttemptTime; }
|
||||||
public void SetLastProcSuccessTime(DateTime lastProcSuccessTime) { m_lastProcSuccessTime = lastProcSuccessTime; }
|
public void SetLastProcSuccessTime(DateTime lastProcSuccessTime) { m_lastProcSuccessTime = lastProcSuccessTime; }
|
||||||
|
|
||||||
|
public UnitAura ToUnitAura() { if (GetAuraType() == AuraObjectType.Unit) return (UnitAura)this; else return null; }
|
||||||
|
|
||||||
|
public DynObjAura ToDynObjAura() { if (GetAuraType() == AuraObjectType.DynObj) return (DynObjAura)this; else return null; }
|
||||||
|
|
||||||
|
|
||||||
//Static Methods
|
//Static Methods
|
||||||
public static uint BuildEffectMaskForOwner(SpellInfo spellProto, uint availableEffectMask, WorldObject owner)
|
public static uint BuildEffectMaskForOwner(SpellInfo spellProto, uint availableEffectMask, WorldObject owner)
|
||||||
{
|
{
|
||||||
@@ -2382,22 +2416,23 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
return (effMask & availableEffectMask);
|
return (effMask & availableEffectMask);
|
||||||
}
|
}
|
||||||
public static Aura TryRefreshStackOrCreate(SpellInfo spellproto, ObjectGuid castId, uint tryEffMask, WorldObject owner, Unit caster, Difficulty castDifficulty, int[] baseAmount = null, Item castItem = null, ObjectGuid casterGUID = default, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = default, uint castItemId = 0, int castItemLevel = -1)
|
public static Aura TryRefreshStackOrCreate(AuraCreateInfo createInfo)
|
||||||
{
|
{
|
||||||
return TryRefreshStackOrCreate(spellproto, castId, tryEffMask, owner, caster, castDifficulty, out _, baseAmount, castItem, casterGUID, resetPeriodicTimer, castItemGuid, castItemId, castItemLevel);
|
Cypher.Assert(createInfo.Caster != null || !createInfo.CasterGUID.IsEmpty());
|
||||||
}
|
|
||||||
public static Aura TryRefreshStackOrCreate(SpellInfo spellproto, ObjectGuid castId, uint tryEffMask, WorldObject owner, Unit caster, Difficulty castDifficulty, out bool refresh, int[] baseAmount, Item castItem = null, ObjectGuid casterGUID = default, bool resetPeriodicTimer = true, ObjectGuid castItemGuid = default, uint castItemId = 0, int castItemLevel = -1)
|
createInfo.IsRefresh = false;
|
||||||
{
|
|
||||||
Cypher.Assert(spellproto != null);
|
createInfo._auraEffectMask = BuildEffectMaskForOwner(createInfo.GetSpellInfo(), createInfo.GetAuraEffectMask(), createInfo.GetOwner());
|
||||||
Cypher.Assert(owner != null);
|
createInfo._targetEffectMask &= createInfo._auraEffectMask;
|
||||||
Cypher.Assert(caster || !casterGUID.IsEmpty());
|
|
||||||
Cypher.Assert(tryEffMask <= SpellConst.MaxEffectMask);
|
uint effMask = createInfo._auraEffectMask;
|
||||||
refresh = false;
|
if (createInfo._targetEffectMask != 0)
|
||||||
|
effMask = createInfo._targetEffectMask;
|
||||||
|
|
||||||
uint effMask = BuildEffectMaskForOwner(spellproto, tryEffMask, owner);
|
|
||||||
if (effMask == 0)
|
if (effMask == 0)
|
||||||
return null;
|
return null;
|
||||||
Aura foundAura = owner.ToUnit()._TryStackingOrRefreshingExistingAura(spellproto, effMask, caster, baseAmount, castItem, casterGUID, resetPeriodicTimer, castItemGuid, castItemId, castItemLevel);
|
|
||||||
|
Aura foundAura = createInfo.GetOwner().ToUnit()._TryStackingOrRefreshingExistingAura(createInfo);
|
||||||
if (foundAura != null)
|
if (foundAura != null)
|
||||||
{
|
{
|
||||||
// we've here aura, which script triggered removal after modding stack amount
|
// we've here aura, which script triggered removal after modding stack amount
|
||||||
@@ -2405,65 +2440,95 @@ namespace Game.Spells
|
|||||||
if (foundAura.IsRemoved())
|
if (foundAura.IsRemoved())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
refresh = true;
|
createInfo.IsRefresh = true;
|
||||||
|
|
||||||
|
// add owner
|
||||||
|
Unit unit = createInfo.GetOwner().ToUnit();
|
||||||
|
|
||||||
|
// check effmask on owner application (if existing)
|
||||||
|
AuraApplication aurApp = foundAura.GetApplicationOfTarget(unit.GetGUID());
|
||||||
|
if (aurApp != null)
|
||||||
|
aurApp.UpdateApplyEffectMask(effMask);
|
||||||
return foundAura;
|
return foundAura;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return Create(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
|
return Create(createInfo);
|
||||||
}
|
}
|
||||||
public static Aura TryCreate(SpellInfo spellproto, ObjectGuid castId, uint tryEffMask, WorldObject owner, Unit caster, Difficulty castDifficulty, int[] baseAmount, Item castItem = null, ObjectGuid casterGUID = default, ObjectGuid castItemGuid = default, uint castItemId = 0, int castItemLevel = -1)
|
|
||||||
|
public static Aura TryCreate(AuraCreateInfo createInfo)
|
||||||
{
|
{
|
||||||
Cypher.Assert(spellproto != null);
|
Cypher.Assert(createInfo.Caster != null || !createInfo.CasterGUID.IsEmpty());
|
||||||
Cypher.Assert(owner != null);
|
|
||||||
Cypher.Assert(caster != null || !casterGUID.IsEmpty());
|
uint effMask = createInfo._auraEffectMask;
|
||||||
Cypher.Assert(tryEffMask <= SpellConst.MaxEffectMask);
|
if (createInfo._targetEffectMask != 0)
|
||||||
uint effMask = BuildEffectMaskForOwner(spellproto, tryEffMask, owner);
|
effMask = createInfo._targetEffectMask;
|
||||||
|
|
||||||
|
effMask = BuildEffectMaskForOwner(createInfo.GetSpellInfo(), effMask, createInfo.GetOwner());
|
||||||
if (effMask == 0)
|
if (effMask == 0)
|
||||||
return null;
|
return null;
|
||||||
return Create(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
|
|
||||||
|
return Create(createInfo);
|
||||||
}
|
}
|
||||||
public static Aura Create(SpellInfo spellproto, ObjectGuid castId, uint effMask, WorldObject owner, Unit caster, Difficulty castDifficulty, int[] baseAmount, Item castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint castItemId, int castItemLevel)
|
|
||||||
|
public static Aura Create(AuraCreateInfo createInfo)
|
||||||
{
|
{
|
||||||
Cypher.Assert(effMask != 0);
|
Cypher.Assert(createInfo.Caster != null || !createInfo.CasterGUID.IsEmpty());
|
||||||
Cypher.Assert(spellproto != null);
|
|
||||||
Cypher.Assert(owner != null);
|
|
||||||
Cypher.Assert(caster != null || !casterGUID.IsEmpty());
|
|
||||||
Cypher.Assert(effMask <= SpellConst.MaxEffectMask);
|
|
||||||
// try to get caster of aura
|
// try to get caster of aura
|
||||||
if (!casterGUID.IsEmpty())
|
if (!createInfo.CasterGUID.IsEmpty())
|
||||||
{
|
{
|
||||||
if (owner.GetGUID() == casterGUID)
|
if (createInfo.GetOwner().GetGUID() == createInfo.CasterGUID)
|
||||||
caster = owner.ToUnit();
|
createInfo.Caster = createInfo.GetOwner().ToUnit();
|
||||||
else
|
else
|
||||||
caster = Global.ObjAccessor.GetUnit(owner, casterGUID);
|
createInfo.Caster = Global.ObjAccessor.GetUnit(createInfo.GetOwner(), createInfo.CasterGUID);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
casterGUID = caster.GetGUID();
|
createInfo.CasterGUID = createInfo.Caster.GetGUID();
|
||||||
|
|
||||||
// check if aura can be owned by owner
|
// check if aura can be owned by owner
|
||||||
if (owner.IsTypeMask(TypeMask.Unit))
|
if (createInfo.GetOwner().IsTypeMask(TypeMask.Unit))
|
||||||
if (!owner.IsInWorld || owner.ToUnit().IsDuringRemoveFromWorld())
|
if (!createInfo.GetOwner().IsInWorld || createInfo.GetOwner().ToUnit().IsDuringRemoveFromWorld())
|
||||||
// owner not in world so don't allow to own not self casted single target auras
|
// owner not in world so don't allow to own not self casted single target auras
|
||||||
if (casterGUID != owner.GetGUID() && spellproto.IsSingleTarget())
|
if (createInfo.CasterGUID != createInfo.GetOwner().GetGUID() && createInfo.GetSpellInfo().IsSingleTarget())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
Aura aura;
|
Aura aura;
|
||||||
switch (owner.GetTypeId())
|
switch (createInfo.GetOwner().GetTypeId())
|
||||||
{
|
{
|
||||||
case TypeId.Unit:
|
case TypeId.Unit:
|
||||||
case TypeId.Player:
|
case TypeId.Player:
|
||||||
aura = new UnitAura(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
|
aura = new UnitAura(createInfo);
|
||||||
|
|
||||||
|
// aura can be removed in Unit::_AddAura call
|
||||||
|
if (aura.IsRemoved())
|
||||||
|
return null;
|
||||||
|
|
||||||
|
// add owner
|
||||||
|
uint effMask = createInfo._auraEffectMask;
|
||||||
|
if (createInfo._targetEffectMask != 0)
|
||||||
|
effMask = createInfo._targetEffectMask;
|
||||||
|
|
||||||
|
effMask = BuildEffectMaskForOwner(createInfo.GetSpellInfo(), effMask, createInfo.GetOwner());
|
||||||
|
Cypher.Assert(effMask != 0);
|
||||||
|
|
||||||
|
Unit unit = createInfo.GetOwner().ToUnit();
|
||||||
|
aura.ToUnitAura().AddStaticApplication(unit, effMask);
|
||||||
break;
|
break;
|
||||||
case TypeId.DynamicObject:
|
case TypeId.DynamicObject:
|
||||||
aura = new DynObjAura(spellproto, castId, effMask, owner, caster, castDifficulty, baseAmount, castItem, casterGUID, castItemGuid, castItemId, castItemLevel);
|
createInfo._auraEffectMask = BuildEffectMaskForOwner(createInfo.GetSpellInfo(), createInfo._auraEffectMask, createInfo.GetOwner());
|
||||||
|
Cypher.Assert(createInfo._auraEffectMask != 0);
|
||||||
|
|
||||||
|
aura = new DynObjAura(createInfo);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
Cypher.Assert(false);
|
Cypher.Assert(false);
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
// aura can be removed in Unit:_AddAura call
|
|
||||||
|
// scripts, etc.
|
||||||
if (aura.IsRemoved())
|
if (aura.IsRemoved())
|
||||||
return null;
|
return null;
|
||||||
|
|
||||||
return aura;
|
return aura;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -2504,19 +2569,18 @@ namespace Game.Spells
|
|||||||
DateTime m_lastProcAttemptTime;
|
DateTime m_lastProcAttemptTime;
|
||||||
DateTime m_lastProcSuccessTime;
|
DateTime m_lastProcSuccessTime;
|
||||||
|
|
||||||
List<AuraApplication> m_removedApplications = new();
|
List<AuraApplication> _removedApplications = new();
|
||||||
#endregion
|
#endregion
|
||||||
}
|
}
|
||||||
|
|
||||||
public class UnitAura : Aura
|
public class UnitAura : Aura
|
||||||
{
|
{
|
||||||
public UnitAura(SpellInfo spellproto, ObjectGuid castId, uint effMask, WorldObject owner, Unit caster, Difficulty castDifficulty, int[] baseAmount, Item castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint castItemId, int castItemLevel)
|
public UnitAura(AuraCreateInfo createInfo) : base(createInfo)
|
||||||
: base(spellproto, castId, owner, caster, castDifficulty, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
|
|
||||||
{
|
{
|
||||||
m_AuraDRGroup = DiminishingGroup.None;
|
m_AuraDRGroup = DiminishingGroup.None;
|
||||||
LoadScripts();
|
LoadScripts();
|
||||||
_InitEffects(effMask, caster, baseAmount);
|
_InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
|
||||||
GetUnitOwner()._AddAura(this, caster);
|
GetUnitOwner()._AddAura(this, createInfo.Caster);
|
||||||
}
|
}
|
||||||
|
|
||||||
public override void _ApplyForTarget(Unit target, Unit caster, AuraApplication aurApp)
|
public override void _ApplyForTarget(Unit target, Unit caster, AuraApplication aurApp)
|
||||||
@@ -2548,114 +2612,129 @@ namespace Game.Spells
|
|||||||
if (refe == null)
|
if (refe == null)
|
||||||
refe = GetUnitOwner();
|
refe = GetUnitOwner();
|
||||||
|
|
||||||
|
// add non area aura targets
|
||||||
|
// static applications go through spell system first, so we assume they meet conditions
|
||||||
|
foreach (var targetPair in _staticApplications)
|
||||||
|
{
|
||||||
|
Unit target = Global.ObjAccessor.GetUnit(GetUnitOwner(), targetPair.Key);
|
||||||
|
if (target != null)
|
||||||
|
targets.Add(target, targetPair.Value);
|
||||||
|
}
|
||||||
|
|
||||||
foreach (SpellEffectInfo effect in GetSpellInfo().GetEffects())
|
foreach (SpellEffectInfo effect in GetSpellInfo().GetEffects())
|
||||||
{
|
{
|
||||||
if (effect == null || !HasEffect(effect.EffectIndex))
|
if (effect == null || !HasEffect(effect.EffectIndex))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
List<Unit> targetList = new();
|
// area auras only
|
||||||
var condList = effect.ImplicitTargetConditions;
|
|
||||||
// non-area aura
|
|
||||||
if (effect.Effect == SpellEffectName.ApplyAura)
|
if (effect.Effect == SpellEffectName.ApplyAura)
|
||||||
{
|
continue;
|
||||||
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(GetUnitOwner(), refe, condList))
|
|
||||||
targetList.Add(GetUnitOwner());
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// skip area update if owner is not in world!
|
|
||||||
if (!GetUnitOwner().IsInWorld)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (GetUnitOwner().HasUnitState(UnitState.Isolated))
|
// skip area update if owner is not in world!
|
||||||
continue;
|
if (!GetUnitOwner().IsInWorld)
|
||||||
|
continue;
|
||||||
|
|
||||||
float radius = effect.CalcRadius(caster);
|
if (GetUnitOwner().HasUnitState(UnitState.Isolated))
|
||||||
SpellTargetCheckTypes selectionType = SpellTargetCheckTypes.Default;
|
continue;
|
||||||
switch (effect.Effect)
|
|
||||||
|
List<Unit> units = new();
|
||||||
|
var condList = effect.ImplicitTargetConditions;
|
||||||
|
|
||||||
|
float radius = effect.CalcRadius(refe);
|
||||||
|
SpellTargetCheckTypes selectionType = SpellTargetCheckTypes.Default;
|
||||||
|
switch (effect.Effect)
|
||||||
|
{
|
||||||
|
case SpellEffectName.ApplyAreaAuraParty:
|
||||||
|
case SpellEffectName.ApplyAreaAuraPartyNonrandom:
|
||||||
|
selectionType = SpellTargetCheckTypes.Party;
|
||||||
|
break;
|
||||||
|
case SpellEffectName.ApplyAreaAuraRaid:
|
||||||
|
selectionType = SpellTargetCheckTypes.Raid;
|
||||||
|
break;
|
||||||
|
case SpellEffectName.ApplyAreaAuraFriend:
|
||||||
|
selectionType = SpellTargetCheckTypes.Ally;
|
||||||
|
break;
|
||||||
|
case SpellEffectName.ApplyAreaAuraEnemy:
|
||||||
|
selectionType = SpellTargetCheckTypes.Enemy;
|
||||||
|
break;
|
||||||
|
case SpellEffectName.ApplyAreaAuraPet:
|
||||||
|
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(GetUnitOwner(), refe, condList))
|
||||||
|
units.Add(GetUnitOwner());
|
||||||
|
goto case SpellEffectName.ApplyAreaAuraOwner;
|
||||||
|
/* fallthrough */
|
||||||
|
case SpellEffectName.ApplyAreaAuraOwner:
|
||||||
{
|
{
|
||||||
case SpellEffectName.ApplyAreaAuraParty:
|
Unit owner = GetUnitOwner().GetCharmerOrOwner();
|
||||||
case SpellEffectName.ApplyAreaAuraPartyNonrandom:
|
if (owner != null)
|
||||||
selectionType = SpellTargetCheckTypes.Party;
|
if (GetUnitOwner().IsWithinDistInMap(owner, radius))
|
||||||
break;
|
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(owner, refe, condList))
|
||||||
case SpellEffectName.ApplyAreaAuraRaid:
|
units.Add(owner);
|
||||||
selectionType = SpellTargetCheckTypes.Raid;
|
break;
|
||||||
break;
|
|
||||||
case SpellEffectName.ApplyAreaAuraFriend:
|
|
||||||
selectionType = SpellTargetCheckTypes.Ally;
|
|
||||||
break;
|
|
||||||
case SpellEffectName.ApplyAreaAuraEnemy:
|
|
||||||
selectionType = SpellTargetCheckTypes.Enemy;
|
|
||||||
break;
|
|
||||||
case SpellEffectName.ApplyAreaAuraPet:
|
|
||||||
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(GetUnitOwner(), refe, condList))
|
|
||||||
targetList.Add(GetUnitOwner());
|
|
||||||
goto case SpellEffectName.ApplyAreaAuraOwner;
|
|
||||||
case SpellEffectName.ApplyAreaAuraOwner:
|
|
||||||
{
|
|
||||||
Unit owner = GetUnitOwner().GetCharmerOrOwner();
|
|
||||||
if (owner != null)
|
|
||||||
if (GetUnitOwner().IsWithinDistInMap(owner, radius))
|
|
||||||
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(owner, refe, condList))
|
|
||||||
targetList.Add(owner);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SpellEffectName.ApplyAuraOnPet:
|
|
||||||
{
|
|
||||||
Unit pet = Global.ObjAccessor.GetUnit(GetUnitOwner(), GetUnitOwner().GetPetGUID());
|
|
||||||
if (pet != null)
|
|
||||||
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(pet, refe, condList))
|
|
||||||
targetList.Add(pet);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
case SpellEffectName.ApplyAreaAuraSummons:
|
|
||||||
{
|
|
||||||
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(GetUnitOwner(), refe, condList))
|
|
||||||
targetList.Add(GetUnitOwner());
|
|
||||||
|
|
||||||
selectionType = SpellTargetCheckTypes.Summoned;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
case SpellEffectName.ApplyAuraOnPet:
|
||||||
if (selectionType != SpellTargetCheckTypes.Default)
|
|
||||||
{
|
{
|
||||||
WorldObjectSpellAreaTargetCheck check = new(radius, GetUnitOwner(), refe, GetUnitOwner(), GetSpellInfo(), selectionType, condList, SpellTargetObjectTypes.Unit);
|
Unit pet = Global.ObjAccessor.GetUnit(GetUnitOwner(), GetUnitOwner().GetPetGUID());
|
||||||
UnitListSearcher searcher = new(GetUnitOwner(), targetList, check);
|
if (pet != null)
|
||||||
Cell.VisitAllObjects(GetUnitOwner(), searcher, radius);
|
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(pet, refe, condList))
|
||||||
|
units.Add(pet);
|
||||||
// by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
|
break;
|
||||||
targetList.RemoveAll(unit => !unit.IsSelfOrInSameMap(GetUnitOwner()));
|
}
|
||||||
|
case SpellEffectName.ApplyAreaAuraSummons:
|
||||||
|
{
|
||||||
|
if (condList == null || Global.ConditionMgr.IsObjectMeetToConditions(GetUnitOwner(), refe, condList))
|
||||||
|
units.Add(GetUnitOwner());
|
||||||
|
selectionType = SpellTargetCheckTypes.Summoned;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
foreach (var unit in targetList)
|
if (selectionType != SpellTargetCheckTypes.Default)
|
||||||
{
|
{
|
||||||
if (targets.ContainsKey(unit))
|
WorldObjectSpellAreaTargetCheck check = new(radius, GetUnitOwner(), refe, GetUnitOwner(), GetSpellInfo(), selectionType, condList, SpellTargetObjectTypes.Unit);
|
||||||
targets[unit] |= (1u << (int)effect.EffectIndex);
|
UnitListSearcher searcher = new(GetUnitOwner(), units, check);
|
||||||
else
|
Cell.VisitAllObjects(GetUnitOwner(), searcher, radius);
|
||||||
targets[unit] = (1u << (int)effect.EffectIndex);
|
|
||||||
|
// by design WorldObjectSpellAreaTargetCheck allows not-in-world units (for spells) but for auras it is not acceptable
|
||||||
|
units.RemoveAll(unit => !unit.IsSelfOrInSameMap(GetUnitOwner()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
foreach (Unit unit in units)
|
||||||
|
targets[unit] |= 1u << (int)effect.EffectIndex;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public void AddStaticApplication(Unit target, uint effMask)
|
||||||
|
{
|
||||||
|
// only valid for non-area auras
|
||||||
|
foreach (SpellEffectInfo effect in GetSpellInfo().GetEffects())
|
||||||
|
{
|
||||||
|
if (effect != null && (effMask & (1u << (int)effect.EffectIndex)) != 0 && effect.Effect != SpellEffectName.ApplyAura)
|
||||||
|
effMask &= ~(1u << (int)effect.EffectIndex);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (effMask == 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
_staticApplications[target.GetGUID()] |= effMask;
|
||||||
|
}
|
||||||
|
|
||||||
// Allow Apply Aura Handler to modify and access m_AuraDRGroup
|
// Allow Apply Aura Handler to modify and access m_AuraDRGroup
|
||||||
public void SetDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }
|
public void SetDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }
|
||||||
public DiminishingGroup GetDiminishGroup() { return m_AuraDRGroup; }
|
public DiminishingGroup GetDiminishGroup() { return m_AuraDRGroup; }
|
||||||
|
|
||||||
DiminishingGroup m_AuraDRGroup; // Diminishing
|
DiminishingGroup m_AuraDRGroup; // Diminishing
|
||||||
|
Dictionary<ObjectGuid, uint> _staticApplications = new(); // non-area auras
|
||||||
}
|
}
|
||||||
|
|
||||||
public class DynObjAura : Aura
|
public class DynObjAura : Aura
|
||||||
{
|
{
|
||||||
public DynObjAura(SpellInfo spellproto, ObjectGuid castId, uint effMask, WorldObject owner, Unit caster, Difficulty castDifficulty, int[] baseAmount, Item castItem, ObjectGuid casterGUID, ObjectGuid castItemGuid, uint castItemId, int castItemLevel)
|
public DynObjAura(AuraCreateInfo createInfo) : base(createInfo)
|
||||||
: base(spellproto, castId, owner, caster, castDifficulty, castItem, casterGUID, castItemGuid, castItemId, castItemLevel)
|
|
||||||
{
|
{
|
||||||
LoadScripts();
|
LoadScripts();
|
||||||
Cypher.Assert(GetDynobjOwner() != null);
|
Cypher.Assert(GetDynobjOwner() != null);
|
||||||
Cypher.Assert(GetDynobjOwner().IsInWorld);
|
Cypher.Assert(GetDynobjOwner().IsInWorld);
|
||||||
Cypher.Assert(GetDynobjOwner().GetMap() == caster.GetMap());
|
Cypher.Assert(GetDynobjOwner().GetMap() == createInfo.Caster.GetMap());
|
||||||
_InitEffects(effMask, caster, baseAmount);
|
_InitEffects(createInfo._auraEffectMask, createInfo.Caster, createInfo.BaseAmount);
|
||||||
GetDynobjOwner().SetAura(this);
|
GetDynobjOwner().SetAura(this);
|
||||||
|
|
||||||
}
|
}
|
||||||
@@ -2693,12 +2772,7 @@ namespace Game.Spells
|
|||||||
targetList.RemoveAll(unit => !unit.IsSelfOrInSameMap(GetDynobjOwner()));
|
targetList.RemoveAll(unit => !unit.IsSelfOrInSameMap(GetDynobjOwner()));
|
||||||
|
|
||||||
foreach (var unit in targetList)
|
foreach (var unit in targetList)
|
||||||
{
|
targets[unit] |= 1u << (int)effect.EffectIndex;
|
||||||
if (targets.ContainsKey(unit))
|
|
||||||
targets[unit] |= (1u << (int)effect.EffectIndex);
|
|
||||||
else
|
|
||||||
targets[unit] = (1u << (int)effect.EffectIndex);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2774,4 +2848,51 @@ namespace Game.Spells
|
|||||||
public int[] Amounts = new int[SpellConst.MaxEffects];
|
public int[] Amounts = new int[SpellConst.MaxEffects];
|
||||||
public int[] BaseAmounts = new int[SpellConst.MaxEffects];
|
public int[] BaseAmounts = new int[SpellConst.MaxEffects];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class AuraCreateInfo
|
||||||
|
{
|
||||||
|
public ObjectGuid CasterGUID;
|
||||||
|
public Unit Caster;
|
||||||
|
public int[] BaseAmount;
|
||||||
|
public ObjectGuid CastItemGUID;
|
||||||
|
public uint CastItemId = 0;
|
||||||
|
public int CastItemLevel = -1;
|
||||||
|
public bool IsRefresh;
|
||||||
|
public bool ResetPeriodicTimer = true;
|
||||||
|
|
||||||
|
internal ObjectGuid _castId;
|
||||||
|
internal SpellInfo _spellInfo;
|
||||||
|
internal Difficulty _castDifficulty;
|
||||||
|
internal uint _auraEffectMask;
|
||||||
|
internal WorldObject _owner;
|
||||||
|
|
||||||
|
internal uint _targetEffectMask;
|
||||||
|
|
||||||
|
public AuraCreateInfo(ObjectGuid castId, SpellInfo spellInfo, Difficulty castDifficulty, uint auraEffMask, WorldObject owner)
|
||||||
|
{
|
||||||
|
_castId = castId;
|
||||||
|
_spellInfo = spellInfo;
|
||||||
|
_castDifficulty = castDifficulty;
|
||||||
|
_auraEffectMask = auraEffMask;
|
||||||
|
_owner = owner;
|
||||||
|
|
||||||
|
Cypher.Assert(spellInfo != null);
|
||||||
|
Cypher.Assert(auraEffMask != 0);
|
||||||
|
Cypher.Assert(owner != null);
|
||||||
|
|
||||||
|
Cypher.Assert(auraEffMask <= SpellConst.MaxEffectMask);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void SetCasterGUID(ObjectGuid guid) { CasterGUID = guid; }
|
||||||
|
public void SetCaster(Unit caster) { Caster = caster; }
|
||||||
|
public void SetBaseAmount(int[] bp) { BaseAmount = bp; }
|
||||||
|
public void SetCastItem(ObjectGuid guid, uint itemId, int itemLevel) { CastItemGUID = guid; CastItemId = itemId; CastItemLevel = itemLevel; }
|
||||||
|
public void SetPeriodicReset(bool reset) { ResetPeriodicTimer = reset; }
|
||||||
|
public void SetOwnerEffectMask(uint effMask) { _targetEffectMask = effMask; }
|
||||||
|
public void SetAuraEffectMask(uint effMask) { _auraEffectMask = effMask; }
|
||||||
|
|
||||||
|
public SpellInfo GetSpellInfo() { return _spellInfo; }
|
||||||
|
public uint GetAuraEffectMask() { return _auraEffectMask; }
|
||||||
|
public WorldObject GetOwner() { return _owner; }
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
+35
-25
@@ -1938,8 +1938,6 @@ namespace Game.Spells
|
|||||||
ProcFlags procVictim = m_procVictim;
|
ProcFlags procVictim = m_procVictim;
|
||||||
ProcFlagsHit hitMask = ProcFlagsHit.None;
|
ProcFlagsHit hitMask = ProcFlagsHit.None;
|
||||||
|
|
||||||
m_spellAura = null;
|
|
||||||
|
|
||||||
//Spells with this flag cannot trigger if effect is cast on self
|
//Spells with this flag cannot trigger if effect is cast on self
|
||||||
bool canEffectTrigger = !m_spellInfo.HasAttribute(SpellAttr3.CantTriggerProc) && unitTarget.CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SpellMissInfo.Immune || missInfo == SpellMissInfo.Immune2);
|
bool canEffectTrigger = !m_spellInfo.HasAttribute(SpellAttr3.CantTriggerProc) && unitTarget.CanProc() && (CanExecuteTriggersOnHit(mask) || missInfo == SpellMissInfo.Immune || missInfo == SpellMissInfo.Immune2);
|
||||||
|
|
||||||
@@ -2228,10 +2226,7 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
uint aura_effmask = 0;
|
uint aura_effmask = Aura.BuildEffectMaskForOwner(m_spellInfo, effectMask, unit);
|
||||||
foreach (SpellEffectInfo effect in m_spellInfo.GetEffects())
|
|
||||||
if (effect != null && (Convert.ToBoolean(effectMask & (1 << (int)effect.EffectIndex)) && effect.IsUnitOwnedAuraEffect()))
|
|
||||||
aura_effmask |= (1u << (int)effect.EffectIndex);
|
|
||||||
|
|
||||||
// Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
|
// Get Data Needed for Diminishing Returns, some effects may have multiple auras, so this must be done on spell hit, not aura add
|
||||||
DiminishingGroup diminishGroup = m_spellInfo.GetDiminishingReturnsGroupForSpell();
|
DiminishingGroup diminishGroup = m_spellInfo.GetDiminishingReturnsGroupForSpell();
|
||||||
@@ -2256,19 +2251,35 @@ namespace Game.Spells
|
|||||||
basePoints[auraSpellEffect.EffectIndex] = (m_spellValue.CustomBasePointsMask & (1 << (int)auraSpellEffect.EffectIndex)) != 0 ?
|
basePoints[auraSpellEffect.EffectIndex] = (m_spellValue.CustomBasePointsMask & (1 << (int)auraSpellEffect.EffectIndex)) != 0 ?
|
||||||
m_spellValue.EffectBasePoints[auraSpellEffect.EffectIndex] : auraSpellEffect.CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel);
|
m_spellValue.EffectBasePoints[auraSpellEffect.EffectIndex] : auraSpellEffect.CalcBaseValue(m_originalCaster, unit, m_castItemEntry, m_castItemLevel);
|
||||||
|
|
||||||
bool refresh;
|
AuraCreateInfo createInfo = null;
|
||||||
bool resetPeriodicTimer = !_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.DontResetPeriodicTimer);
|
if (spellAura == null)
|
||||||
m_spellAura = Aura.TryRefreshStackOrCreate(m_spellInfo, m_castId, effectMask, unit,
|
{
|
||||||
m_originalCaster, GetCastDifficulty(), out refresh, basePoints, m_CastItem, ObjectGuid.Empty, resetPeriodicTimer, ObjectGuid.Empty, m_castItemEntry, m_castItemLevel);
|
bool resetPeriodicTimer = !_triggeredCastFlags.HasFlag(TriggerCastFlags.DontResetPeriodicTimer);
|
||||||
if (m_spellAura != null)
|
uint allAuraEffectMask = Aura.BuildEffectMaskForOwner(m_spellInfo, SpellConst.MaxEffectMask, unit);
|
||||||
|
|
||||||
|
createInfo = new(m_castId, m_spellInfo, GetCastDifficulty(), allAuraEffectMask, unit);
|
||||||
|
createInfo.SetCaster(m_originalCaster);
|
||||||
|
createInfo.SetBaseAmount(basePoints);
|
||||||
|
createInfo.SetCastItem(m_castItemGUID, m_castItemEntry, m_castItemLevel);
|
||||||
|
createInfo.SetPeriodicReset(resetPeriodicTimer);
|
||||||
|
createInfo.SetOwnerEffectMask(aura_effmask);
|
||||||
|
|
||||||
|
Aura aura = Aura.TryRefreshStackOrCreate(createInfo);
|
||||||
|
if (aura != null)
|
||||||
|
spellAura = aura.ToUnitAura();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
spellAura.AddStaticApplication(unit, aura_effmask);
|
||||||
|
|
||||||
|
if (spellAura != null)
|
||||||
{
|
{
|
||||||
// Set aura stack amount to desired value
|
// Set aura stack amount to desired value
|
||||||
if (m_spellValue.AuraStackAmount > 1)
|
if (m_spellValue.AuraStackAmount > 1)
|
||||||
{
|
{
|
||||||
if (!refresh)
|
if (createInfo != null && createInfo.IsRefresh)
|
||||||
m_spellAura.SetStackAmount((byte)m_spellValue.AuraStackAmount);
|
spellAura.SetStackAmount((byte)m_spellValue.AuraStackAmount);
|
||||||
else
|
else
|
||||||
m_spellAura.ModStackAmount(m_spellValue.AuraStackAmount);
|
spellAura.ModStackAmount(m_spellValue.AuraStackAmount);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Now Reduce spell duration using data received at spell hit
|
// Now Reduce spell duration using data received at spell hit
|
||||||
@@ -2287,12 +2298,13 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
int duration = m_spellAura.GetMaxDuration();
|
int duration = spellAura.GetMaxDuration();
|
||||||
|
|
||||||
// unit is immune to aura if it was diminished to 0 duration
|
// unit is immune to aura if it was diminished to 0 duration
|
||||||
if (!positive && !unit.ApplyDiminishingToDuration(m_spellInfo, ref duration, m_originalCaster, diminishLevel))
|
if (!positive && !unit.ApplyDiminishingToDuration(m_spellInfo, ref duration, m_originalCaster, diminishLevel))
|
||||||
{
|
{
|
||||||
m_spellAura.Remove();
|
spellAura.Remove();
|
||||||
|
spellAura = null;
|
||||||
bool found = false;
|
bool found = false;
|
||||||
foreach (SpellEffectInfo effect in m_spellInfo.GetEffects())
|
foreach (SpellEffectInfo effect in m_spellInfo.GetEffects())
|
||||||
if (effect != null && (Convert.ToBoolean(effectMask & (1 << (int)effect.EffectIndex)) && effect.Effect != SpellEffectName.ApplyAura))
|
if (effect != null && (Convert.ToBoolean(effectMask & (1 << (int)effect.EffectIndex)) && effect.Effect != SpellEffectName.ApplyAura))
|
||||||
@@ -2302,7 +2314,7 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
((UnitAura)m_spellAura).SetDiminishGroup(diminishGroup);
|
spellAura.SetDiminishGroup(diminishGroup);
|
||||||
|
|
||||||
duration = m_originalCaster.ModSpellDuration(m_spellInfo, unit, duration, positive, effectMask);
|
duration = m_originalCaster.ModSpellDuration(m_spellInfo, unit, duration, positive, effectMask);
|
||||||
if (duration > 0)
|
if (duration > 0)
|
||||||
@@ -2320,7 +2332,7 @@ namespace Game.Spells
|
|||||||
{
|
{
|
||||||
if (effect != null)
|
if (effect != null)
|
||||||
{
|
{
|
||||||
AuraEffect eff = m_spellAura.GetEffect(effect.EffectIndex);
|
AuraEffect eff = spellAura.GetEffect(effect.EffectIndex);
|
||||||
if (eff != null)
|
if (eff != null)
|
||||||
{
|
{
|
||||||
int period = eff.GetPeriod();
|
int period = eff.GetPeriod();
|
||||||
@@ -2336,12 +2348,11 @@ namespace Game.Spells
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (duration != m_spellAura.GetMaxDuration())
|
if (duration != spellAura.GetMaxDuration())
|
||||||
{
|
{
|
||||||
m_spellAura.SetMaxDuration(duration);
|
spellAura.SetMaxDuration(duration);
|
||||||
m_spellAura.SetDuration(duration);
|
spellAura.SetDuration(duration);
|
||||||
}
|
}
|
||||||
m_spellAura._RegisterForTargets();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -3216,8 +3227,6 @@ namespace Game.Spells
|
|||||||
|
|
||||||
void _handle_immediate_phase()
|
void _handle_immediate_phase()
|
||||||
{
|
{
|
||||||
m_spellAura = null;
|
|
||||||
|
|
||||||
// handle some immediate features of the spell here
|
// handle some immediate features of the spell here
|
||||||
HandleThreatSpells();
|
HandleThreatSpells();
|
||||||
|
|
||||||
@@ -7632,7 +7641,8 @@ namespace Game.Spells
|
|||||||
SpellEffectHandleMode effectHandleMode;
|
SpellEffectHandleMode effectHandleMode;
|
||||||
public SpellEffectInfo effectInfo;
|
public SpellEffectInfo effectInfo;
|
||||||
// used in effects handlers
|
// used in effects handlers
|
||||||
public Aura m_spellAura;
|
internal UnitAura spellAura;
|
||||||
|
internal DynObjAura dynObjAura;
|
||||||
|
|
||||||
// -------------------------------------------
|
// -------------------------------------------
|
||||||
GameObject focusObject;
|
GameObject focusObject;
|
||||||
|
|||||||
@@ -707,11 +707,10 @@ namespace Game.Spells
|
|||||||
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
|
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_spellAura == null || unitTarget == null)
|
if (spellAura == null || unitTarget == null)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
Cypher.Assert(unitTarget == m_spellAura.GetOwner());
|
spellAura._ApplyEffectForTargets(effIndex);
|
||||||
m_spellAura._ApplyEffectForTargets(effIndex);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
[SpellEffectHandler(SpellEffectName.ApplyAreaAuraEnemy)]
|
[SpellEffectHandler(SpellEffectName.ApplyAreaAuraEnemy)]
|
||||||
@@ -727,10 +726,10 @@ namespace Game.Spells
|
|||||||
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
|
if (effectHandleMode != SpellEffectHandleMode.HitTarget)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_spellAura == null || unitTarget == null)
|
if (spellAura == null || unitTarget == null)
|
||||||
return;
|
return;
|
||||||
Cypher.Assert(unitTarget == m_spellAura.GetOwner());
|
|
||||||
m_spellAura._ApplyEffectForTargets(effIndex);
|
spellAura._ApplyEffectForTargets(effIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
[SpellEffectHandler(SpellEffectName.UnlearnSpecialization)]
|
[SpellEffectHandler(SpellEffectName.UnlearnSpecialization)]
|
||||||
@@ -1150,30 +1149,46 @@ namespace Game.Spells
|
|||||||
if (effectHandleMode != SpellEffectHandleMode.Hit)
|
if (effectHandleMode != SpellEffectHandleMode.Hit)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
if (m_spellAura == null)
|
// only handle at last effect
|
||||||
|
for (uint i = effIndex + 1; i < SpellConst.MaxEffects; ++i)
|
||||||
{
|
{
|
||||||
Unit caster = m_caster.GetEntry() == SharedConst.WorldTrigger ? m_originalCaster : m_caster;
|
SpellEffectInfo otherEffect = m_spellInfo.GetEffect(i);
|
||||||
float radius = effectInfo.CalcRadius(caster);
|
if (otherEffect != null && otherEffect.IsEffect(SpellEffectName.PersistentAreaAura))
|
||||||
|
|
||||||
// Caster not in world, might be spell triggered from aura removal
|
|
||||||
if (!caster.IsInWorld)
|
|
||||||
return;
|
|
||||||
DynamicObject dynObj = new(false);
|
|
||||||
if (!dynObj.CreateDynamicObject(caster.GetMap().GenerateLowGuid(HighGuid.DynamicObject), caster, m_spellInfo, destTarget, radius, DynamicObjectType.AreaSpell, m_SpellVisual))
|
|
||||||
return;
|
|
||||||
|
|
||||||
Aura aura = Aura.TryCreate(m_spellInfo, m_castId, SpellConst.MaxEffectMask, dynObj, caster, GetCastDifficulty(), m_spellValue.EffectBasePoints, null, ObjectGuid.Empty, ObjectGuid.Empty, m_castItemEntry, m_castItemLevel);
|
|
||||||
if (aura != null)
|
|
||||||
{
|
|
||||||
m_spellAura = aura;
|
|
||||||
m_spellAura._RegisterForTargets();
|
|
||||||
}
|
|
||||||
else
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
Cypher.Assert(m_spellAura.GetDynobjOwner());
|
Cypher.Assert(dynObjAura == null);
|
||||||
m_spellAura._ApplyEffectForTargets(effIndex);
|
|
||||||
|
Unit caster = m_caster.GetEntry() == SharedConst.WorldTrigger ? m_originalCaster : m_caster;
|
||||||
|
float radius = effectInfo.CalcRadius(caster);
|
||||||
|
|
||||||
|
// Caster not in world, might be spell triggered from aura removal
|
||||||
|
if (!caster.IsInWorld)
|
||||||
|
return;
|
||||||
|
|
||||||
|
DynamicObject dynObj = new(false);
|
||||||
|
if (!dynObj.CreateDynamicObject(caster.GetMap().GenerateLowGuid(HighGuid.DynamicObject), caster, m_spellInfo, destTarget, radius, DynamicObjectType.AreaSpell, m_SpellVisual))
|
||||||
|
{
|
||||||
|
dynObj.Dispose();
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
AuraCreateInfo createInfo = new(m_castId, m_spellInfo, GetCastDifficulty(), SpellConst.MaxEffectMask, dynObj);
|
||||||
|
createInfo.SetCaster(caster);
|
||||||
|
createInfo.SetBaseAmount(m_spellValue.EffectBasePoints);
|
||||||
|
createInfo.SetCastItem(m_castItemGUID, m_castItemEntry, m_castItemLevel);
|
||||||
|
|
||||||
|
Aura aura = Aura.TryCreate(createInfo);
|
||||||
|
if (aura != null)
|
||||||
|
{
|
||||||
|
dynObjAura = aura.ToDynObjAura();
|
||||||
|
dynObjAura._RegisterForTargets();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
return;
|
||||||
|
|
||||||
|
Cypher.Assert(dynObjAura.GetDynobjOwner());
|
||||||
|
dynObjAura._ApplyEffectForTargets(effIndex);
|
||||||
}
|
}
|
||||||
|
|
||||||
[SpellEffectHandler(SpellEffectName.Energize)]
|
[SpellEffectHandler(SpellEffectName.Energize)]
|
||||||
|
|||||||
Reference in New Issue
Block a user