Core/Spells: Rename SpellAttr2 to use official attribute names
Port From (https://github.com/TrinityCore/TrinityCore/commit/dda375b9868d6dbe2a4d58b386bb90ae41d25e0d)
This commit is contained in:
@@ -698,7 +698,7 @@ namespace Game.Spells
|
||||
{
|
||||
if (m_timeCla > diff)
|
||||
m_timeCla -= (int)diff;
|
||||
else if (caster != null)
|
||||
else if (caster != null && (caster == GetOwner() || !GetSpellInfo().HasAttribute(SpellAttr2.NoTargetPerSecondCosts)))
|
||||
{
|
||||
if (!m_periodicCosts.Empty())
|
||||
{
|
||||
@@ -1008,7 +1008,7 @@ namespace Game.Spells
|
||||
{
|
||||
return GetCasterGUID() == target.GetGUID()
|
||||
&& m_spellInfo.Stances != 0
|
||||
&& !m_spellInfo.HasAttribute(SpellAttr2.NotNeedShapeshift)
|
||||
&& !m_spellInfo.HasAttribute(SpellAttr2.AllowWhileNotShapeshiftedCasterForm)
|
||||
&& !m_spellInfo.HasAttribute(SpellAttr0.NotShapeshifted);
|
||||
}
|
||||
|
||||
@@ -1644,9 +1644,19 @@ namespace Game.Spells
|
||||
return m_procCooldown > now;
|
||||
}
|
||||
|
||||
public void AddProcCooldown(DateTime cooldownEnd)
|
||||
public void AddProcCooldown(SpellProcEntry procEntry, DateTime now)
|
||||
{
|
||||
m_procCooldown = cooldownEnd;
|
||||
// cooldowns should be added to the whole aura (see 51698 area aura)
|
||||
int procCooldown = (int)procEntry.Cooldown;
|
||||
Unit caster = GetCaster();
|
||||
if (caster != null)
|
||||
{
|
||||
Player modOwner = caster.GetSpellModOwner();
|
||||
if (modOwner != null)
|
||||
modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ProcCooldown, ref procCooldown);
|
||||
}
|
||||
|
||||
m_procCooldown = now + TimeSpan.FromMilliseconds(procCooldown);
|
||||
}
|
||||
|
||||
public void ResetProcCooldown()
|
||||
@@ -1663,26 +1673,36 @@ namespace Game.Spells
|
||||
SpellProcEntry procEntry = Global.SpellMgr.GetSpellProcEntry(GetSpellInfo());
|
||||
Cypher.Assert(procEntry != null);
|
||||
|
||||
PrepareProcChargeDrop(procEntry, eventInfo);
|
||||
|
||||
// cooldowns should be added to the whole aura (see 51698 area aura)
|
||||
AddProcCooldown(procEntry, now);
|
||||
|
||||
SetLastProcSuccessTime(now);
|
||||
}
|
||||
|
||||
public void PrepareProcChargeDrop(SpellProcEntry procEntry, ProcEventInfo eventInfo)
|
||||
{
|
||||
// take one charge, aura expiration will be handled in Aura.TriggerProcOnEvent (if needed)
|
||||
if (!procEntry.AttributesMask.HasAnyFlag(ProcAttributes.UseStacksForCharges) && IsUsingCharges() && (eventInfo.GetSpellInfo() == null || !eventInfo.GetSpellInfo().HasAttribute(SpellAttr6.DoNotConsumeResources)))
|
||||
{
|
||||
--m_procCharges;
|
||||
SetNeedClientUpdateForTargets();
|
||||
}
|
||||
}
|
||||
|
||||
// cooldowns should be added to the whole aura (see 51698 area aura)
|
||||
int procCooldown = (int)procEntry.Cooldown;
|
||||
Unit caster = GetCaster();
|
||||
if (caster != null)
|
||||
public void ConsumeProcCharges(SpellProcEntry procEntry)
|
||||
{
|
||||
// Remove aura if we've used last charge to proc
|
||||
if (procEntry.AttributesMask.HasFlag(ProcAttributes.UseStacksForCharges))
|
||||
{
|
||||
Player modOwner = caster.GetSpellModOwner();
|
||||
if (modOwner != null)
|
||||
modOwner.ApplySpellMod(GetSpellInfo(), SpellModOp.ProcCooldown, ref procCooldown);
|
||||
ModStackAmount(-1);
|
||||
}
|
||||
else if (IsUsingCharges())
|
||||
{
|
||||
if (GetCharges() == 0)
|
||||
Remove();
|
||||
}
|
||||
|
||||
AddProcCooldown(now + TimeSpan.FromMilliseconds(procCooldown));
|
||||
|
||||
SetLastProcSuccessTime(now);
|
||||
}
|
||||
|
||||
public uint GetProcEffectMask(AuraApplication aurApp, ProcEventInfo eventInfo, DateTime now)
|
||||
@@ -1859,16 +1879,7 @@ namespace Game.Spells
|
||||
CallScriptAfterProcHandlers(aurApp, eventInfo);
|
||||
}
|
||||
|
||||
// Remove aura if we've used last charge to proc
|
||||
if (Global.SpellMgr.GetSpellProcEntry(m_spellInfo).AttributesMask.HasAnyFlag(ProcAttributes.UseStacksForCharges))
|
||||
{
|
||||
ModStackAmount(-1);
|
||||
}
|
||||
else if (IsUsingCharges())
|
||||
{
|
||||
if (GetCharges() == 0)
|
||||
Remove();
|
||||
}
|
||||
ConsumeProcCharges(Global.SpellMgr.GetSpellProcEntry(GetSpellInfo()));
|
||||
}
|
||||
|
||||
public float CalcPPMProcChance(Unit actor)
|
||||
|
||||
@@ -1308,7 +1308,7 @@ namespace Game.Spells
|
||||
}
|
||||
|
||||
if (!shapeInfo.Flags.HasAnyFlag(SpellShapeshiftFormFlags.Stance))
|
||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Shapeshifting, GetId());
|
||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Shapeshifting, GetSpellInfo());
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -2837,7 +2837,7 @@ namespace Game.Spells
|
||||
|
||||
// remove all flag auras (they are positive, but they must be removed when you are immune)
|
||||
if (GetSpellInfo().HasAttribute(SpellAttr1.ImmunityPurgesEffect)
|
||||
&& GetSpellInfo().HasAttribute(SpellAttr2.DamageReducedShield))
|
||||
&& GetSpellInfo().HasAttribute(SpellAttr2.FailOnAllTargetsImmune))
|
||||
target.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.StealthOrInvis);
|
||||
}
|
||||
|
||||
@@ -5206,10 +5206,6 @@ namespace Game.Spells
|
||||
return;
|
||||
}
|
||||
|
||||
// heal for caster damage (must be alive)
|
||||
if (target != caster && GetSpellInfo().HasAttribute(SpellAttr2.HealthFunnel) && (caster == null || !caster.IsAlive()))
|
||||
return;
|
||||
|
||||
// don't regen when permanent aura target has full power
|
||||
if (GetBase().IsPermanent() && target.IsFullHealth())
|
||||
return;
|
||||
|
||||
+64
-18
@@ -95,6 +95,10 @@ namespace Game.Spells
|
||||
|
||||
m_spellState = SpellState.None;
|
||||
_triggeredCastFlags = triggerFlags;
|
||||
|
||||
if (info.HasAttribute(SpellAttr2.DoNotReportSpellFailure))
|
||||
_triggeredCastFlags = _triggeredCastFlags | TriggerCastFlags.DontReportCastError;
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr4.CanCastWhileCasting))
|
||||
_triggeredCastFlags = _triggeredCastFlags | TriggerCastFlags.IgnoreCastInProgress;
|
||||
|
||||
@@ -274,6 +278,35 @@ namespace Game.Spells
|
||||
if (m_targets.HasDst())
|
||||
AddDestTarget(m_targets.GetDst(), spellEffectInfo.EffectIndex);
|
||||
|
||||
if (spellEffectInfo.TargetA.GetObjectType() == SpellTargetObjectTypes.Unit
|
||||
|| spellEffectInfo.TargetA.GetObjectType() == SpellTargetObjectTypes.UnitAndDest
|
||||
|| spellEffectInfo.TargetB.GetObjectType() == SpellTargetObjectTypes.Unit
|
||||
|| spellEffectInfo.TargetB.GetObjectType() == SpellTargetObjectTypes.UnitAndDest)
|
||||
{
|
||||
if (m_spellInfo.HasAttribute(SpellAttr1.RequireAllTargets))
|
||||
{
|
||||
bool noTargetFound = !m_UniqueTargetInfo.Any(target => (target.EffectMask & 1 << (int)spellEffectInfo.EffectIndex) != 0);
|
||||
|
||||
if (noTargetFound)
|
||||
{
|
||||
SendCastResult(m_spellInfo.Id == 51690 ? SpellCastResult.OutOfRange : SpellCastResult.BadTargets);
|
||||
Finish(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.FailOnAllTargetsImmune))
|
||||
{
|
||||
bool anyNonImmuneTargetFound = m_UniqueTargetInfo.Any(target => (target.EffectMask & 1 << (int)spellEffectInfo.EffectIndex) != 0 && target.MissCondition != SpellMissInfo.Immune && target.MissCondition != SpellMissInfo.Immune2);
|
||||
|
||||
if (!anyNonImmuneTargetFound)
|
||||
{
|
||||
SendCastResult(SpellCastResult.Immune);
|
||||
Finish(false);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (m_spellInfo.IsChanneled())
|
||||
{
|
||||
// maybe do this for all spells?
|
||||
@@ -1621,8 +1654,9 @@ namespace Game.Spells
|
||||
if (isBouncingFar)
|
||||
searchRadius *= chainTargets;
|
||||
|
||||
WorldObject chainSource = m_spellInfo.HasAttribute(SpellAttr2.ChainFromCaster) ? m_caster : target;
|
||||
List<WorldObject> tempTargets = new();
|
||||
SearchAreaTargets(tempTargets, searchRadius, target.GetPosition(), m_caster, objectType, selectType, condList);
|
||||
SearchAreaTargets(tempTargets, searchRadius, chainSource, m_caster, objectType, selectType, condList);
|
||||
tempTargets.Remove(target);
|
||||
|
||||
// remove targets which are always invalid for chain spells
|
||||
@@ -1651,7 +1685,7 @@ namespace Game.Spells
|
||||
if (unitTarget != null)
|
||||
{
|
||||
uint deficit = (uint)(unitTarget.GetMaxHealth() - unitTarget.GetHealth());
|
||||
if ((deficit > maxHPDeficit || found == null) && target.IsWithinDist(unitTarget, jumpRadius) && target.IsWithinLOSInMap(unitTarget, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
if ((deficit > maxHPDeficit || found == null) && chainSource.IsWithinDist(unitTarget, jumpRadius) && chainSource.IsWithinLOSInMap(unitTarget, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
{
|
||||
found = obj;
|
||||
maxHPDeficit = deficit;
|
||||
@@ -1666,19 +1700,22 @@ namespace Game.Spells
|
||||
{
|
||||
if (found == null)
|
||||
{
|
||||
if ((!isBouncingFar || target.IsWithinDist(obj, jumpRadius)) && target.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
if ((!isBouncingFar || chainSource.IsWithinDist(obj, jumpRadius)) && chainSource.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
found = obj;
|
||||
}
|
||||
else if (target.GetDistanceOrder(obj, found) && target.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
else if (chainSource.GetDistanceOrder(obj, found) && chainSource.IsWithinLOSInMap(obj, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
found = obj;
|
||||
}
|
||||
}
|
||||
// not found any valid target - chain ends
|
||||
if (found == null)
|
||||
break;
|
||||
target = found;
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.ChainFromCaster))
|
||||
chainSource = found;
|
||||
|
||||
targets.Add(found);
|
||||
tempTargets.Remove(found);
|
||||
targets.Add(target);
|
||||
--chainTargets;
|
||||
}
|
||||
}
|
||||
@@ -1712,7 +1749,7 @@ namespace Game.Spells
|
||||
break;
|
||||
case SpellDmgClass.Ranged:
|
||||
// Auto attack
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag))
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.AutoRepeat))
|
||||
{
|
||||
m_procAttacker = new ProcFlagsInit(ProcFlags.DealRangedAttack);
|
||||
m_procVictim = new ProcFlagsInit(ProcFlags.TakeRangedAttack);
|
||||
@@ -1726,7 +1763,7 @@ namespace Game.Spells
|
||||
default:
|
||||
if (m_spellInfo.EquippedItemClass == ItemClass.Weapon &&
|
||||
Convert.ToBoolean(m_spellInfo.EquippedItemSubClassMask & (1 << (int)ItemSubClassWeapon.Wand))
|
||||
&& m_spellInfo.HasAttribute(SpellAttr2.AutorepeatFlag)) // Wands auto attack
|
||||
&& m_spellInfo.HasAttribute(SpellAttr2.AutoRepeat)) // Wands auto attack
|
||||
{
|
||||
m_procAttacker = new ProcFlagsInit(ProcFlags.DealRangedAttack);
|
||||
m_procVictim = new ProcFlagsInit(ProcFlags.TakeRangedAttack);
|
||||
@@ -2488,8 +2525,8 @@ namespace Game.Spells
|
||||
{
|
||||
// stealth must be removed at cast starting (at show channel bar)
|
||||
// skip triggered spell (item equip spell casting and other not explicit character casts/item uses)
|
||||
if (!_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.IgnoreAuraInterruptFlags) && m_spellInfo.IsBreakingStealth() && !m_spellInfo.HasAttribute(SpellAttr2.IgnoreActionAuraInterruptFlags))
|
||||
unitCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Action);
|
||||
if (!_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.IgnoreAuraInterruptFlags) && !m_spellInfo.HasAttribute(SpellAttr2.NotAnAction))
|
||||
unitCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.Action, m_spellInfo);
|
||||
|
||||
// Do not register as current spell when requested to ignore cast in progress
|
||||
// We don't want to interrupt that other spell with cast time
|
||||
@@ -2903,8 +2940,8 @@ namespace Game.Spells
|
||||
if (!hitMask.HasAnyFlag(ProcFlagsHit.Critical))
|
||||
hitMask |= ProcFlagsHit.Normal;
|
||||
|
||||
if (!_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.IgnoreAuraInterruptFlags) && !m_spellInfo.HasAttribute(SpellAttr2.IgnoreActionAuraInterruptFlags))
|
||||
m_originalCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.ActionDelayed);
|
||||
if (!_triggeredCastFlags.HasAnyFlag(TriggerCastFlags.IgnoreAuraInterruptFlags) && !m_spellInfo.HasAttribute(SpellAttr2.NotAnAction))
|
||||
m_originalCaster.RemoveAurasWithInterruptFlags(SpellAuraInterruptFlags.ActionDelayed, m_spellInfo);
|
||||
|
||||
Unit.ProcSkillsAndAuras(m_originalCaster, null, procAttacker, new ProcFlagsInit(ProcFlags.None), ProcFlagsSpellType.MaskAll, ProcFlagsSpellPhase.Cast, hitMask, this, null, null);
|
||||
|
||||
@@ -3340,7 +3377,7 @@ namespace Game.Spells
|
||||
|
||||
if (IsAutoActionResetSpell())
|
||||
{
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.NotResetAutoActions))
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.DoNotResetCombatTimers))
|
||||
{
|
||||
unitCaster.ResetAttackTimer(WeaponAttackType.BaseAttack);
|
||||
if (unitCaster.HaveOffhandWeapon())
|
||||
@@ -4566,7 +4603,7 @@ namespace Game.Spells
|
||||
if (m_spellInfo.HasAttribute(SpellAttr0.UsesRangedSlot)
|
||||
|| m_spellInfo.IsNextMeleeSwingSpell()
|
||||
|| m_spellInfo.HasAttribute(SpellAttr1.InitiatesCombatEnablesAutoAttack)
|
||||
|| m_spellInfo.HasAttribute(SpellAttr2.Unk20)
|
||||
|| m_spellInfo.HasAttribute(SpellAttr2.InitiateCombatPostCastEnablesAutoAttack)
|
||||
|| m_spellInfo.HasEffect(SpellEffectName.Attack)
|
||||
|| m_spellInfo.HasEffect(SpellEffectName.NormalizedWeaponDmg)
|
||||
|| m_spellInfo.HasEffect(SpellEffectName.WeaponDamageNoSchool)
|
||||
@@ -4787,7 +4824,7 @@ namespace Game.Spells
|
||||
losTarget = dynObj;
|
||||
}
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.CanTargetNotInLos) && !m_spellInfo.HasAttribute(SpellAttr5.AlwaysAoeLineOfSight) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS)
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight) && !m_spellInfo.HasAttribute(SpellAttr5.AlwaysAoeLineOfSight) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS)
|
||||
&& !unitTarget.IsWithinLOSInMap(losTarget, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
return SpellCastResult.LineOfSight;
|
||||
}
|
||||
@@ -4800,7 +4837,7 @@ namespace Game.Spells
|
||||
float x, y, z;
|
||||
m_targets.GetDstPos().GetPosition(out x, out y, out z);
|
||||
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.CanTargetNotInLos) && !m_spellInfo.HasAttribute(SpellAttr5.AlwaysAoeLineOfSight) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS)
|
||||
if (!m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight) && !m_spellInfo.HasAttribute(SpellAttr5.AlwaysAoeLineOfSight) && !Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS)
|
||||
&& !m_caster.IsWithinLOS(x, y, z, LineOfSightChecks.All, ModelIgnoreFlags.M2))
|
||||
return SpellCastResult.LineOfSight;
|
||||
}
|
||||
@@ -4808,6 +4845,10 @@ namespace Game.Spells
|
||||
// check pet presence
|
||||
if (unitCaster != null)
|
||||
{
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.NoActivePets))
|
||||
if (!unitCaster.GetPetGUID().IsEmpty())
|
||||
return SpellCastResult.AlreadyHavePet;
|
||||
|
||||
foreach (var spellEffectInfo in m_spellInfo.GetEffects())
|
||||
{
|
||||
if (spellEffectInfo.TargetA.GetTarget() == Targets.UnitPet)
|
||||
@@ -5697,6 +5738,9 @@ namespace Game.Spells
|
||||
if (m_CastItem != null)
|
||||
return SpellCastResult.ItemEnchantTradeWindow;
|
||||
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.EnchantOwnItemOnly))
|
||||
return SpellCastResult.ItemEnchantTradeWindow;
|
||||
|
||||
if (!m_caster.IsTypeId(TypeId.Player))
|
||||
return SpellCastResult.NotTrading;
|
||||
|
||||
@@ -6964,7 +7008,7 @@ namespace Game.Spells
|
||||
}
|
||||
|
||||
// check for ignore LOS on the effect itself
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.CanTargetNotInLos) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS))
|
||||
if (m_spellInfo.HasAttribute(SpellAttr2.IgnoreLineOfSight) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_spellInfo.Id, null, (byte)DisableFlags.SpellLOS))
|
||||
return true;
|
||||
|
||||
// check if gameobject ignores LOS
|
||||
@@ -6974,7 +7018,7 @@ namespace Game.Spells
|
||||
return true;
|
||||
|
||||
// if spell is triggered, need to check for LOS disable on the aura triggering it and inherit that behaviour
|
||||
if (IsTriggered() && m_triggeredByAuraSpell != null && (m_triggeredByAuraSpell.HasAttribute(SpellAttr2.CanTargetNotInLos) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_triggeredByAuraSpell.Id, null, (byte)DisableFlags.SpellLOS)))
|
||||
if (IsTriggered() && m_triggeredByAuraSpell != null && (m_triggeredByAuraSpell.HasAttribute(SpellAttr2.IgnoreLineOfSight) || Global.DisableMgr.IsDisabledFor(DisableType.Spell, m_triggeredByAuraSpell.Id, null, (byte)DisableFlags.SpellLOS)))
|
||||
return true;
|
||||
|
||||
// @todo shit below shouldn't be here, but it's temporary
|
||||
@@ -9052,6 +9096,7 @@ namespace Game.Spells
|
||||
{
|
||||
public TriggerCastFlags TriggerFlags;
|
||||
public Item CastItem;
|
||||
public Spell TriggeringSpell;
|
||||
public AuraEffect TriggeringAura;
|
||||
public ObjectGuid OriginalCaster = ObjectGuid.Empty;
|
||||
public Difficulty CastDifficulty;
|
||||
@@ -9113,6 +9158,7 @@ namespace Game.Spells
|
||||
|
||||
public CastSpellExtraArgs SetTriggeringSpell(Spell triggeringSpell)
|
||||
{
|
||||
TriggeringSpell = triggeringSpell;
|
||||
if (triggeringSpell != null)
|
||||
{
|
||||
OriginalCastItemLevel = triggeringSpell.m_castItemLevel;
|
||||
|
||||
@@ -305,18 +305,26 @@ namespace Game.Spells
|
||||
if (effectInfo.Effect == SpellEffectName.TriggerSpell)
|
||||
delay = TimeSpan.FromMilliseconds(effectInfo.MiscValue);
|
||||
|
||||
CastSpellExtraArgs args = new(TriggerCastFlags.FullMask);
|
||||
args.SetOriginalCaster(m_originalCasterGUID);
|
||||
args.SetTriggeringSpell(this);
|
||||
// set basepoints for trigger with value effect
|
||||
if (effectInfo.Effect == SpellEffectName.TriggerSpellWithValue)
|
||||
for (int i = 0; i < SpellConst.MaxEffects; ++i)
|
||||
args.AddSpellMod(SpellValueMod.BasePoint0 + i, damage);
|
||||
|
||||
m_caster.m_Events.AddEventAtOffset(() =>
|
||||
{
|
||||
// original caster guid only for GO cast
|
||||
m_caster.CastSpell(targets, triggered_spell_id, args);
|
||||
CastSpellExtraArgs args = new(TriggerCastFlags.FullMask);
|
||||
args.SetOriginalCaster(m_originalCasterGUID);
|
||||
args.OriginalCastId = m_castId;
|
||||
args.OriginalCastItemLevel = m_castItemLevel;
|
||||
if (!m_castItemGUID.IsEmpty() && Global.SpellMgr.GetSpellInfo(effectInfo.TriggerSpell, m_caster.GetMap().GetDifficultyID()).HasAttribute(SpellAttr2.RetainItemCast))
|
||||
{
|
||||
Player triggeringAuraCaster = args.TriggeringAura.GetCaster()?.ToPlayer();
|
||||
if (triggeringAuraCaster != null)
|
||||
args.CastItem = triggeringAuraCaster.GetItemByGuid(m_castItemGUID);
|
||||
}
|
||||
|
||||
// set basepoints for trigger with value effect
|
||||
if (effectInfo.Effect == SpellEffectName.TriggerSpellWithValue)
|
||||
for (int i = 0; i < SpellConst.MaxEffects; ++i)
|
||||
args.AddSpellMod(SpellValueMod.BasePoint0 + i, damage);
|
||||
|
||||
m_caster.CastSpell(targets, effectInfo.TriggerSpell, args);
|
||||
}, delay);
|
||||
}
|
||||
|
||||
|
||||
@@ -499,7 +499,7 @@ namespace Game.Spells
|
||||
|
||||
public bool IsAllowingDeadTarget()
|
||||
{
|
||||
if (HasAttribute(SpellAttr2.CanTargetDead) || Targets.HasAnyFlag(SpellCastTargetFlags.CorpseAlly | SpellCastTargetFlags.CorpseEnemy | SpellCastTargetFlags.UnitDead))
|
||||
if (HasAttribute(SpellAttr2.AllowDeadTarget) || Targets.HasAnyFlag(SpellCastTargetFlags.CorpseAlly | SpellCastTargetFlags.CorpseEnemy | SpellCastTargetFlags.UnitDead))
|
||||
return true;
|
||||
|
||||
foreach (var effectInfo in _effects)
|
||||
@@ -566,11 +566,6 @@ namespace Game.Spells
|
||||
return HasAttribute(SpellAttr0.OnNextSwingNoDamage | SpellAttr0.OnNextSwing);
|
||||
}
|
||||
|
||||
public bool IsBreakingStealth()
|
||||
{
|
||||
return !HasAttribute(SpellAttr1.AllowWhileStealthed);
|
||||
}
|
||||
|
||||
public bool IsRangedWeaponSpell()
|
||||
{
|
||||
return (SpellFamilyName == SpellFamilyNames.Hunter && !SpellFamilyFlags[1].HasAnyFlag(0x10000000u)) // for 53352, cannot find better way
|
||||
@@ -580,12 +575,12 @@ namespace Game.Spells
|
||||
|
||||
public bool IsAutoRepeatRangedSpell()
|
||||
{
|
||||
return HasAttribute(SpellAttr2.AutorepeatFlag);
|
||||
return HasAttribute(SpellAttr2.AutoRepeat);
|
||||
}
|
||||
|
||||
public bool HasInitialAggro()
|
||||
{
|
||||
return !(HasAttribute(SpellAttr1.NoThreat) || HasAttribute(SpellAttr3.NoInitialAggro));
|
||||
return !(HasAttribute(SpellAttr1.NoThreat) || HasAttribute(SpellAttr2.NoInitialThreat));
|
||||
}
|
||||
|
||||
public bool HasHitDelay()
|
||||
@@ -689,7 +684,7 @@ namespace Game.Spells
|
||||
return true;
|
||||
|
||||
// these spells (Cyclone for example) can pierce all...
|
||||
if (HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) || HasAttribute(SpellAttr2.UnaffectedByAuraSchoolImmune))
|
||||
if (HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) || HasAttribute(SpellAttr2.NoSchoolImmunities))
|
||||
{
|
||||
// ...but not these (Divine shield, Ice block, Cyclone and Banish for example)
|
||||
if (auraSpellInfo.Mechanic != Mechanics.ImmuneShield &&
|
||||
@@ -717,7 +712,7 @@ namespace Game.Spells
|
||||
|
||||
// These auras (Cyclone for example) are not dispelable
|
||||
if ((auraSpellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && auraSpellInfo.Mechanic != Mechanics.None)
|
||||
|| auraSpellInfo.HasAttribute(SpellAttr2.UnaffectedByAuraSchoolImmune))
|
||||
|| auraSpellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
@@ -835,7 +830,7 @@ namespace Game.Spells
|
||||
else
|
||||
{
|
||||
// needs shapeshift
|
||||
if (!HasAttribute(SpellAttr2.NotNeedShapeshift) && Stances != 0)
|
||||
if (!HasAttribute(SpellAttr2.AllowWhileNotShapeshiftedCasterForm) && Stances != 0)
|
||||
return SpellCastResult.OnlyShapeshift;
|
||||
}
|
||||
|
||||
@@ -1043,7 +1038,7 @@ namespace Game.Spells
|
||||
if (caster.IsTypeId(TypeId.Player))
|
||||
{
|
||||
// Do not allow these spells to target creatures not tapped by us (Banish, Polymorph, many quest spells)
|
||||
if (HasAttribute(SpellAttr2.CantTargetTapped))
|
||||
if (HasAttribute(SpellAttr2.CannotCastOnTapped))
|
||||
{
|
||||
Creature targetCreature = unitTarget.ToCreature();
|
||||
if (targetCreature != null)
|
||||
@@ -2509,7 +2504,7 @@ namespace Game.Spells
|
||||
|
||||
ImmunityInfo immuneInfo = effectInfo.GetImmunityInfo();
|
||||
|
||||
if (!auraSpellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && !auraSpellInfo.HasAttribute(SpellAttr2.UnaffectedByAuraSchoolImmune))
|
||||
if (!auraSpellInfo.HasAttribute(SpellAttr1.ImmunityToHostileAndFriendlyEffects) && !auraSpellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities))
|
||||
{
|
||||
uint schoolImmunity = immuneInfo.SchoolImmuneMask;
|
||||
if (schoolImmunity != 0)
|
||||
@@ -2558,7 +2553,7 @@ namespace Game.Spells
|
||||
if (!immuneInfo.AuraTypeImmune.Contains(auraName))
|
||||
isImmuneToAuraEffectApply = true;
|
||||
|
||||
if (!isImmuneToAuraEffectApply && !auraSpellInfo.IsPositiveEffect(auraSpellEffectInfo.EffectIndex) && !auraSpellInfo.HasAttribute(SpellAttr2.UnaffectedByAuraSchoolImmune))
|
||||
if (!isImmuneToAuraEffectApply && !auraSpellInfo.IsPositiveEffect(auraSpellEffectInfo.EffectIndex) && !auraSpellInfo.HasAttribute(SpellAttr2.NoSchoolImmunities))
|
||||
{
|
||||
uint applyHarmfulAuraImmunityMask = immuneInfo.ApplyHarmfulAuraImmuneMask;
|
||||
if (applyHarmfulAuraImmunityMask != 0)
|
||||
@@ -2604,7 +2599,7 @@ namespace Game.Spells
|
||||
break;
|
||||
case AuraType.SchoolImmunity:
|
||||
case AuraType.ModImmuneAuraApplySchool:
|
||||
if (aurEff.GetSpellInfo().HasAttribute(SpellAttr2.UnaffectedByAuraSchoolImmune) || !Convert.ToBoolean((uint)aurEff.GetSpellInfo().SchoolMask & miscValue))
|
||||
if (aurEff.GetSpellInfo().HasAttribute(SpellAttr2.NoSchoolImmunities) || !Convert.ToBoolean((uint)aurEff.GetSpellInfo().SchoolMask & miscValue))
|
||||
continue;
|
||||
break;
|
||||
case AuraType.DispelImmunity:
|
||||
@@ -3180,7 +3175,7 @@ namespace Game.Spells
|
||||
return this;
|
||||
|
||||
// Client ignores spell with these attributes (sub_53D9D0)
|
||||
if (HasAttribute(SpellAttr0.AuraIsDebuff) || HasAttribute(SpellAttr2.Unk3) || HasAttribute(SpellAttr3.DrainSoul))
|
||||
if (HasAttribute(SpellAttr0.AuraIsDebuff) || HasAttribute(SpellAttr2.AllowLowLevelBuff) || HasAttribute(SpellAttr3.DrainSoul))
|
||||
return this;
|
||||
|
||||
bool needRankSelection = false;
|
||||
|
||||
@@ -4098,7 +4098,7 @@ namespace Game.Entities
|
||||
ApplySpellFix(new[] { 75509 }, spellInfo =>
|
||||
{
|
||||
spellInfo.AttributesEx6 |= SpellAttr6.CanTargetInvisible;
|
||||
spellInfo.AttributesEx2 |= SpellAttr2.CanTargetNotInLos;
|
||||
spellInfo.AttributesEx2 |= SpellAttr2.IgnoreLineOfSight;
|
||||
});
|
||||
|
||||
// Awaken Flames
|
||||
@@ -4122,7 +4122,7 @@ namespace Game.Entities
|
||||
{
|
||||
// All spells work even without these changes. The LOS attribute is due to problem
|
||||
// from collision between maps & gos with active destroyed state.
|
||||
spellInfo.AttributesEx2 |= SpellAttr2.CanTargetNotInLos;
|
||||
spellInfo.AttributesEx2 |= SpellAttr2.IgnoreLineOfSight;
|
||||
});
|
||||
|
||||
// Arcane Barrage (cast by players and NONMELEEDAMAGELOG with caster Scion of Eternity (original caster)).
|
||||
@@ -4261,7 +4261,7 @@ namespace Game.Entities
|
||||
ApplySpellFix(new[] { 42525 }, spellInfo =>
|
||||
{
|
||||
spellInfo.AttributesEx3 |= SpellAttr3.DeathPersistent;
|
||||
spellInfo.AttributesEx2 |= SpellAttr2.CanTargetDead;
|
||||
spellInfo.AttributesEx2 |= SpellAttr2.AllowDeadTarget;
|
||||
});
|
||||
|
||||
// Soul Sickness (Forge of Souls)
|
||||
|
||||
Reference in New Issue
Block a user