Implemented binary resistances and some more
Port From (https://github.com/TrinityCore/TrinityCore/commit/ca26c33145cb40ae7fd2c84fc7577fc6f11bdbbf)
This commit is contained in:
@@ -1809,7 +1809,7 @@ namespace Framework.Constants
|
||||
ConeLine = 0x04,
|
||||
ShareDamage = 0x08,
|
||||
NoInitialThreat = 0x10,
|
||||
IsTalent = 0x20,
|
||||
AuraCC = 0x20,
|
||||
DontBreakStealth = 0x40,
|
||||
DirectDamage = 0x100,
|
||||
Charge = 0x200,
|
||||
@@ -1822,6 +1822,10 @@ namespace Framework.Constants
|
||||
ReqCasterBehindTarget = 0x20000,
|
||||
AllowInflightTarget = 0x40000,
|
||||
NeedsAmmoData = 0x80000,
|
||||
BinarySpell = 0x00100000,
|
||||
SchoolmaskNormalWithMagic = 0x00200000,
|
||||
LiquidAura = 0x00400000,
|
||||
IsTalent = 0x00800000,
|
||||
|
||||
Negative = NegativeEff0 | NegativeEff1 | NegativeEff2
|
||||
}
|
||||
|
||||
@@ -1712,13 +1712,18 @@ namespace Game.Entities
|
||||
ForcedDespawn(msTimeToDespawn, forceRespawnTimer);
|
||||
}
|
||||
|
||||
bool HasMechanicTemplateImmunity(uint mask)
|
||||
{
|
||||
return !GetOwnerGUID().IsPlayer() && GetCreatureTemplate().MechanicImmuneMask.HasAnyFlag(mask);
|
||||
}
|
||||
|
||||
public override bool IsImmunedToSpell(SpellInfo spellInfo, Unit caster)
|
||||
{
|
||||
if (spellInfo == null)
|
||||
return false;
|
||||
|
||||
// Creature is immune to main mechanic of the spell
|
||||
if (Convert.ToBoolean(GetCreatureTemplate().MechanicImmuneMask & (1 << ((int)spellInfo.Mechanic - 1))))
|
||||
if (spellInfo.Mechanic > Mechanics.None && HasMechanicTemplateImmunity(1u << ((int)spellInfo.Mechanic - 1)))
|
||||
return true;
|
||||
|
||||
// This check must be done instead of 'if (GetCreatureTemplate().MechanicImmuneMask & (1 << (spellInfo.Mechanic - 1)))' for not break
|
||||
@@ -1735,6 +1740,7 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (immunedToAllEffects)
|
||||
return true;
|
||||
|
||||
@@ -1746,7 +1752,8 @@ namespace Game.Entities
|
||||
SpellEffectInfo effect = spellInfo.GetEffect(GetMap().GetDifficultyID(), index);
|
||||
if (effect == null)
|
||||
return true;
|
||||
if (Convert.ToBoolean(GetCreatureTemplate().MechanicImmuneMask & (1 << ((int)effect.Mechanic - 1))))
|
||||
|
||||
if (effect.Mechanic > Mechanics.None && HasMechanicTemplateImmunity(1u << ((int)effect.Mechanic - 1)))
|
||||
return true;
|
||||
|
||||
if (GetCreatureTemplate().CreatureType == CreatureType.Mechanical && effect.Effect == SpellEffectName.Heal)
|
||||
|
||||
@@ -2290,47 +2290,28 @@ namespace Game.Entities
|
||||
return true;
|
||||
}
|
||||
|
||||
uint CalcSpellResistance(Unit victim, SpellSchoolMask schoolMask, SpellInfo spellInfo)
|
||||
uint CalcSpellResistedDamage(Unit attacker, Unit victim, uint damage, SpellSchoolMask schoolMask, SpellInfo spellInfo)
|
||||
{
|
||||
// Magic damage, check for resists
|
||||
if (!Convert.ToBoolean(schoolMask & SpellSchoolMask.Spell))
|
||||
if (!Convert.ToBoolean(schoolMask & SpellSchoolMask.Magic))
|
||||
return 0;
|
||||
|
||||
// Npcs can have holy resistance
|
||||
if (schoolMask.HasAnyFlag(SpellSchoolMask.Holy) && victim.GetTypeId() != TypeId.Unit)
|
||||
return 0;
|
||||
|
||||
// Ignore spells that can't be resisted
|
||||
if (spellInfo != null && spellInfo.HasAttribute(SpellAttr4.IgnoreResistances))
|
||||
return 0;
|
||||
|
||||
byte bossLevel = 83;
|
||||
uint bossResistanceConstant = 510;
|
||||
uint resistanceConstant = 0;
|
||||
uint level = victim.GetLevelForTarget(this);
|
||||
|
||||
if (level == bossLevel)
|
||||
resistanceConstant = bossResistanceConstant;
|
||||
else
|
||||
resistanceConstant = level * 5;
|
||||
|
||||
int baseVictimResistance = (int)victim.GetResistance(schoolMask);
|
||||
baseVictimResistance += GetTotalAuraModifierByMiscMask(AuraType.ModTargetResistance, (int)schoolMask);
|
||||
|
||||
Player player = ToPlayer();
|
||||
if (player)
|
||||
baseVictimResistance -= player.GetSpellPenetrationItemMod();
|
||||
|
||||
// Resistance can't be lower then 0
|
||||
int victimResistance = Math.Max(baseVictimResistance, 0);
|
||||
|
||||
if (victimResistance > 0)
|
||||
if (spellInfo != null)
|
||||
{
|
||||
int ignoredResistance = GetTotalAuraModifierByMiscMask(AuraType.ModIgnoreTargetResist, (int)schoolMask);
|
||||
ignoredResistance = Math.Min(ignoredResistance, 100);
|
||||
MathFunctions.ApplyPct(ref victimResistance, 100 - ignoredResistance);
|
||||
if (spellInfo.HasAttribute(SpellAttr4.IgnoreResistances))
|
||||
return 0;
|
||||
|
||||
// Binary spells can't have damage part resisted
|
||||
if (spellInfo.HasAttribute(SpellCustomAttributes.BinarySpell))
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (victimResistance <= 0)
|
||||
return 0;
|
||||
|
||||
float averageResist = (float)victimResistance / (float)(victimResistance + resistanceConstant);
|
||||
float averageResist = GetEffectiveResistChance(this, schoolMask, victim, spellInfo);
|
||||
|
||||
float[] discreteResistProbability = new float[11];
|
||||
for (uint i = 0; i < 11; ++i)
|
||||
@@ -2354,7 +2335,69 @@ namespace Game.Entities
|
||||
while (r >= probabilitySum && resistance < 10)
|
||||
probabilitySum += discreteResistProbability[++resistance];
|
||||
|
||||
return resistance * 10;
|
||||
float damageResisted = damage * resistance / 10;
|
||||
if (damageResisted > 0.0f) // if any damage was resisted
|
||||
{
|
||||
int ignoredResistance = 0;
|
||||
|
||||
ignoredResistance += GetTotalAuraModifierByMiscMask(AuraType.ModIgnoreTargetResist, (int)schoolMask);
|
||||
|
||||
ignoredResistance = Math.Min(ignoredResistance, 100);
|
||||
MathFunctions.ApplyPct(ref damageResisted, 100 - ignoredResistance);
|
||||
|
||||
// Spells with melee and magic school mask, decide whether resistance or armor absorb is higher
|
||||
if (spellInfo != null && spellInfo.HasAttribute(SpellCustomAttributes.SchoolmaskNormalWithMagic))
|
||||
{
|
||||
uint damageAfterArmor = CalcArmorReducedDamage(attacker, victim, damage, spellInfo, WeaponAttackType.BaseAttack);
|
||||
uint armorReduction = damage - damageAfterArmor;
|
||||
if (armorReduction < damageResisted) // pick the lower one, the weakest resistance counts
|
||||
damageResisted = armorReduction;
|
||||
}
|
||||
}
|
||||
|
||||
return (uint)damageResisted;
|
||||
}
|
||||
|
||||
float GetEffectiveResistChance(Unit owner, SpellSchoolMask schoolMask, Unit victim, SpellInfo spellInfo)
|
||||
{
|
||||
float victimResistance = (float)victim.GetResistance(schoolMask);
|
||||
if (owner)
|
||||
{
|
||||
// pets inherit 100% of masters penetration
|
||||
// excluding traps
|
||||
Player player = owner.GetSpellModOwner();
|
||||
if (player != null && owner.GetEntry() != SharedConst.WorldTrigger)
|
||||
{
|
||||
victimResistance += (float)player.GetTotalAuraModifierByMiscMask(AuraType.ModTargetResistance, (int)schoolMask);
|
||||
victimResistance -= (float)player.GetSpellPenetrationItemMod();
|
||||
}
|
||||
else
|
||||
victimResistance += (float)owner.GetTotalAuraModifierByMiscMask(AuraType.ModTargetResistance, (int)schoolMask);
|
||||
}
|
||||
|
||||
// holy resistance exists in pve and comes from level difference, ignore template values
|
||||
if (schoolMask.HasAnyFlag(SpellSchoolMask.Holy))
|
||||
victimResistance = 0.0f;
|
||||
|
||||
// Chaos Bolt exception, ignore all target resistances (unknown attribute?)
|
||||
if (spellInfo != null && spellInfo.SpellFamilyName == SpellFamilyNames.Warlock && spellInfo.Id == 116858)
|
||||
victimResistance = 0.0f;
|
||||
|
||||
victimResistance = Math.Max(victimResistance, 0.0f);
|
||||
if (owner)
|
||||
victimResistance += Math.Max((victim.GetLevelForTarget(owner) - owner.GetLevelForTarget(victim)) * 5.0f, 0.0f);
|
||||
|
||||
uint bossLevel = 83;
|
||||
float bossResistanceConstant = 510.0f;
|
||||
uint level = victim.GetLevelForTarget(this);
|
||||
float resistanceConstant = 0.0f;
|
||||
|
||||
if (level == bossLevel)
|
||||
resistanceConstant = bossResistanceConstant;
|
||||
else
|
||||
resistanceConstant = level * 5.0f;
|
||||
|
||||
return victimResistance / (victimResistance + resistanceConstant);
|
||||
}
|
||||
|
||||
public void CalcAbsorbResist(DamageInfo damageInfo)
|
||||
@@ -2362,8 +2405,8 @@ namespace Game.Entities
|
||||
if (!damageInfo.GetVictim() || !damageInfo.GetVictim().IsAlive() || damageInfo.GetDamage() == 0)
|
||||
return;
|
||||
|
||||
uint spellResistance = CalcSpellResistance(damageInfo.GetVictim(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo());
|
||||
damageInfo.ResistDamage(MathFunctions.CalculatePct(damageInfo.GetDamage(), spellResistance));
|
||||
uint resistedDamage = CalcSpellResistedDamage(damageInfo.GetAttacker(), damageInfo.GetVictim(), damageInfo.GetDamage(), damageInfo.GetSchoolMask(), damageInfo.GetSpellInfo());
|
||||
damageInfo.ResistDamage(resistedDamage);
|
||||
|
||||
// Ignore Absorption Auras
|
||||
float auraAbsorbMod = GetMaxPositiveAuraModifierByMiscMask(AuraType.ModTargetAbsorbSchool, (uint)damageInfo.GetSchoolMask());
|
||||
|
||||
@@ -1566,8 +1566,8 @@ namespace Game.Entities
|
||||
if (mechanic != 0)
|
||||
{
|
||||
var mechanicList = m_spellImmune[(int)SpellImmunity.Mechanic];
|
||||
if (mechanicList.ContainsKey(mechanic))
|
||||
return true;
|
||||
if (mechanicList.ContainsKey(mechanic))
|
||||
return true;
|
||||
}
|
||||
|
||||
bool immuneToAllEffects = true;
|
||||
@@ -1588,6 +1588,7 @@ namespace Game.Entities
|
||||
if (immuneToAllEffects) //Return immune only if the target is immune to all spell effects.
|
||||
return true;
|
||||
|
||||
uint schoolImmunityMask = 0;
|
||||
var schoolList = m_spellImmune[(int)SpellImmunity.School];
|
||||
foreach (var pair in schoolList)
|
||||
{
|
||||
@@ -1597,16 +1598,28 @@ namespace Game.Entities
|
||||
SpellInfo immuneSpellInfo = Global.SpellMgr.GetSpellInfo(pair.Value);
|
||||
if (!(immuneSpellInfo != null && immuneSpellInfo.IsPositive() && spellInfo.IsPositive() && caster && IsFriendlyTo(caster)))
|
||||
if (!spellInfo.CanPierceImmuneAura(immuneSpellInfo))
|
||||
return true;
|
||||
schoolImmunityMask |= pair.Key;
|
||||
}
|
||||
|
||||
if (((SpellSchoolMask)schoolImmunityMask & spellInfo.GetSchoolMask()) == spellInfo.GetSchoolMask())
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
public uint GetSchoolImmunityMask()
|
||||
{
|
||||
uint mask = 0;
|
||||
var mechanicList = m_spellImmune[(int)SpellImmunity.School];
|
||||
foreach (var pair in mechanicList)
|
||||
var schoolList = m_spellImmune[(int)SpellImmunity.School];
|
||||
foreach (var pair in schoolList)
|
||||
mask |= pair.Key;
|
||||
|
||||
return mask;
|
||||
}
|
||||
public uint GetDamageImmunityMask()
|
||||
{
|
||||
uint mask = 0;
|
||||
var damageList = m_spellImmune[(int)SpellImmunity.Damage];
|
||||
foreach (var pair in damageList)
|
||||
mask |= pair.Key;
|
||||
|
||||
return mask;
|
||||
@@ -1669,16 +1682,14 @@ namespace Game.Entities
|
||||
public bool IsImmunedToDamage(SpellSchoolMask schoolMask)
|
||||
{
|
||||
// If m_immuneToSchool type contain this school type, IMMUNE damage.
|
||||
var schoolList = m_spellImmune[(int)SpellImmunity.School];
|
||||
foreach (var immune in schoolList)
|
||||
if (Convert.ToBoolean(immune.Key & (uint)schoolMask))
|
||||
return true;
|
||||
uint schoolImmunityMask = GetSchoolImmunityMask();
|
||||
if (((SpellSchoolMask)schoolImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types
|
||||
return true;
|
||||
|
||||
// If m_immuneToDamage type contain magic, IMMUNE damage.
|
||||
var damageList = m_spellImmune[(int)SpellImmunity.Damage];
|
||||
foreach (var immune in damageList)
|
||||
if (Convert.ToBoolean(immune.Key & (uint)schoolMask))
|
||||
return true;
|
||||
uint damageImmunityMask = GetDamageImmunityMask();
|
||||
if (((SpellSchoolMask)damageImmunityMask & schoolMask) == schoolMask) // We need to be immune to all types
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
@@ -2330,8 +2341,12 @@ namespace Game.Entities
|
||||
// Physical Damage
|
||||
if (damageSchoolMask.HasAnyFlag(SpellSchoolMask.Normal))
|
||||
{
|
||||
// Get blocked status
|
||||
blocked = isSpellBlocked(victim, spellInfo, attackType);
|
||||
// Spells with this attribute were already calculated in MeleeSpellHitResult
|
||||
if (!spellInfo.HasAttribute(SpellAttr3.BlockableSpell))
|
||||
{
|
||||
// Get blocked status
|
||||
blocked = isSpellBlocked(victim, spellInfo, attackType);
|
||||
}
|
||||
}
|
||||
|
||||
if (crit)
|
||||
@@ -2567,9 +2582,31 @@ namespace Game.Entities
|
||||
RemoveOwnedAura(pair, AuraRemoveMode.Death);
|
||||
}
|
||||
}
|
||||
public void RemoveMovementImpairingAuras()
|
||||
public void RemoveMovementImpairingAuras(bool withRoot)
|
||||
{
|
||||
RemoveAurasWithMechanic((1 << (int)Mechanics.Snare) | (1 << (int)Mechanics.Root));
|
||||
if (withRoot)
|
||||
RemoveAurasWithMechanic(1 << (int)Mechanics.Root);
|
||||
|
||||
// Snares
|
||||
foreach (var pair in m_appliedAuras)
|
||||
{
|
||||
Aura aura = pair.Value.GetBase();
|
||||
if (aura.GetSpellInfo().Mechanic == Mechanics.Snare)
|
||||
{
|
||||
RemoveAura(pair);
|
||||
continue;
|
||||
}
|
||||
|
||||
// turn off snare auras by setting amount to 0
|
||||
foreach (SpellEffectInfo effect in aura.GetSpellInfo().GetEffectsForDifficulty(GetMap().GetDifficultyID()))
|
||||
{
|
||||
if (effect == null || !effect.IsEffect())
|
||||
continue;
|
||||
|
||||
if (Convert.ToBoolean((1 << (int)effect.EffectIndex) & pair.Value.GetEffectMask()))
|
||||
aura.GetEffect(effect.EffectIndex).ChangeAmount(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
public void RemoveAllAurasRequiringDeadTarget()
|
||||
{
|
||||
@@ -3614,6 +3651,20 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public void RemoveAurasByShapeShift()
|
||||
{
|
||||
uint mechanic_mask = (1 << (int)Mechanics.Snare) | (1 << (int)Mechanics.Root);
|
||||
foreach (var pair in m_appliedAuras)
|
||||
{
|
||||
Aura aura = pair.Value.GetBase();
|
||||
if ((aura.GetSpellInfo().GetAllEffectsMechanicMask() & mechanic_mask) != 0 && !aura.GetSpellInfo().HasAttribute(SpellCustomAttributes.AuraCC))
|
||||
{
|
||||
RemoveAura(pair);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void RemoveAreaAurasDueToLeaveWorld()
|
||||
{
|
||||
// make sure that all area auras not applied on self are removed
|
||||
|
||||
@@ -1310,7 +1310,7 @@ namespace Game.Spells
|
||||
case ShapeShiftForm.MoonkinForm:
|
||||
{
|
||||
// remove movement affects
|
||||
target.RemoveMovementImpairingAuras();
|
||||
target.RemoveAurasByShapeShift();
|
||||
|
||||
// and polymorphic affects
|
||||
if (target.IsPolymorphed())
|
||||
@@ -1351,7 +1351,7 @@ namespace Game.Spells
|
||||
if (target.GetClass() == Class.Druid)
|
||||
{
|
||||
// Remove movement impairing effects also when shifting out
|
||||
target.RemoveMovementImpairingAuras();
|
||||
target.RemoveAurasByShapeShift();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -346,14 +346,14 @@ namespace Game.Spells
|
||||
// Vanish (not exist)
|
||||
case 18461:
|
||||
{
|
||||
unitTarget.RemoveMovementImpairingAuras();
|
||||
unitTarget.RemoveMovementImpairingAuras(true);
|
||||
unitTarget.RemoveAurasByType(AuraType.ModStalked);
|
||||
return;
|
||||
}
|
||||
// Demonic Empowerment -- succubus
|
||||
case 54437:
|
||||
{
|
||||
unitTarget.RemoveMovementImpairingAuras();
|
||||
unitTarget.RemoveMovementImpairingAuras(true);
|
||||
unitTarget.RemoveAurasByType(AuraType.ModStalked);
|
||||
unitTarget.RemoveAurasByType(AuraType.ModStun);
|
||||
|
||||
@@ -1300,49 +1300,6 @@ namespace Game.Spells
|
||||
}
|
||||
|
||||
m_caster.EnergizeBySpell(unitTarget, m_spellInfo.Id, damage, power);
|
||||
|
||||
// Mad Alchemist's Potion
|
||||
if (m_spellInfo.Id == 45051)
|
||||
{
|
||||
// find elixirs on target
|
||||
bool guardianFound = false;
|
||||
bool battleFound = false;
|
||||
foreach (var app in unitTarget.GetAppliedAuras())
|
||||
{
|
||||
uint spell_id = app.Value.GetBase().GetId();
|
||||
if (!guardianFound)
|
||||
if (Global.SpellMgr.IsSpellMemberOfSpellGroup(spell_id, SpellGroup.ElixirGuardian))
|
||||
guardianFound = true;
|
||||
if (!battleFound)
|
||||
if (Global.SpellMgr.IsSpellMemberOfSpellGroup(spell_id, SpellGroup.ElixirBattle))
|
||||
battleFound = true;
|
||||
if (battleFound && guardianFound)
|
||||
break;
|
||||
}
|
||||
|
||||
// get all available elixirs by mask and spell level
|
||||
List<int> avalibleElixirs = new List<int>();
|
||||
if (!guardianFound)
|
||||
Global.SpellMgr.GetSetOfSpellsInSpellGroup(SpellGroup.ElixirGuardian, out avalibleElixirs);
|
||||
if (!battleFound)
|
||||
Global.SpellMgr.GetSetOfSpellsInSpellGroup(SpellGroup.ElixirBattle, out avalibleElixirs);
|
||||
foreach (int spellId in avalibleElixirs)
|
||||
{
|
||||
SpellInfo spellInfo = Global.SpellMgr.GetSpellInfo((uint)spellId);
|
||||
if (spellInfo.SpellLevel < m_spellInfo.SpellLevel || spellInfo.SpellLevel > unitTarget.getLevel())
|
||||
avalibleElixirs.Remove(spellId);
|
||||
else if (Global.SpellMgr.IsSpellMemberOfSpellGroup((uint)spellId, SpellGroup.ElixirShattrath))
|
||||
avalibleElixirs.Remove(spellId);
|
||||
else if (Global.SpellMgr.IsSpellMemberOfSpellGroup((uint)spellId, SpellGroup.ElixirUnstable))
|
||||
avalibleElixirs.Remove(spellId);
|
||||
}
|
||||
|
||||
if (!avalibleElixirs.Empty())
|
||||
{
|
||||
// cast random elixir on target
|
||||
m_caster.CastSpell(unitTarget, (uint)avalibleElixirs.SelectRandom(), true, m_CastItem);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[SpellEffectHandler(SpellEffectName.EnergizePct)]
|
||||
@@ -2988,7 +2945,7 @@ namespace Game.Spells
|
||||
case 30918: // Improved Sprint
|
||||
{
|
||||
// Removes snares and roots.
|
||||
unitTarget.RemoveMovementImpairingAuras();
|
||||
unitTarget.RemoveMovementImpairingAuras(true);
|
||||
break;
|
||||
}
|
||||
// Plant Warmaul Ogre Banner
|
||||
|
||||
@@ -2433,7 +2433,13 @@ namespace Game.Spells
|
||||
target.ApplySpellImmune(Id, SpellImmunity.Mechanic, i, apply);
|
||||
|
||||
if (apply && HasAttribute(SpellAttr1.DispelAurasOnImmunity))
|
||||
target.RemoveAurasWithMechanic(mechanicImmunity, AuraRemoveMode.Default, Id);
|
||||
{
|
||||
// exception for purely snare mechanic (eg. hands of freedom)!
|
||||
if (mechanicImmunity == (1 << (int)Mechanics.Snare))
|
||||
target.RemoveMovementImpairingAuras(false);
|
||||
else
|
||||
target.RemoveAurasWithMechanic(mechanicImmunity, AuraRemoveMode.Default, Id);
|
||||
}
|
||||
}
|
||||
|
||||
uint dispelImmunity = immuneInfo.DispelImmune;
|
||||
|
||||
@@ -2155,6 +2155,14 @@ namespace Game.Entities
|
||||
|
||||
switch (effect.ApplyAuraName)
|
||||
{
|
||||
case AuraType.ModPossess:
|
||||
case AuraType.ModConfuse:
|
||||
case AuraType.ModCharm:
|
||||
case AuraType.AoeCharm:
|
||||
case AuraType.ModFear:
|
||||
case AuraType.ModStun:
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.AuraCC;
|
||||
break;
|
||||
case AuraType.PeriodicHeal:
|
||||
case AuraType.PeriodicDamage:
|
||||
case AuraType.PeriodicDamagePercent:
|
||||
@@ -2232,6 +2240,89 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
// spells ignoring hit result should not be binary
|
||||
if (!spellInfo.HasAttribute(SpellAttr3.IgnoreHitResult))
|
||||
{
|
||||
bool setFlag = false;
|
||||
foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
|
||||
{
|
||||
if (effect == null)
|
||||
continue;
|
||||
|
||||
if (effect.IsEffect())
|
||||
{
|
||||
switch (effect.Effect)
|
||||
{
|
||||
case SpellEffectName.SchoolDamage:
|
||||
case SpellEffectName.WeaponDamage:
|
||||
case SpellEffectName.WeaponDamageNoschool:
|
||||
case SpellEffectName.NormalizedWeaponDmg:
|
||||
case SpellEffectName.WeaponPercentDamage:
|
||||
case SpellEffectName.TriggerSpell:
|
||||
case SpellEffectName.TriggerSpellWithValue:
|
||||
break;
|
||||
case SpellEffectName.PersistentAreaAura:
|
||||
case SpellEffectName.ApplyAura:
|
||||
case SpellEffectName.ApplyAreaAuraParty:
|
||||
case SpellEffectName.ApplyAreaAuraRaid:
|
||||
case SpellEffectName.ApplyAreaAuraFriend:
|
||||
case SpellEffectName.ApplyAreaAuraEnemy:
|
||||
case SpellEffectName.ApplyAreaAuraPet:
|
||||
case SpellEffectName.ApplyAreaAuraOwner:
|
||||
{
|
||||
if (effect.ApplyAuraName == AuraType.PeriodicDamage ||
|
||||
effect.ApplyAuraName == AuraType.PeriodicDamagePercent ||
|
||||
effect.ApplyAuraName == AuraType.PeriodicDummy ||
|
||||
effect.ApplyAuraName == AuraType.PeriodicLeech ||
|
||||
effect.ApplyAuraName == AuraType.PeriodicHealthFunnel ||
|
||||
effect.ApplyAuraName == AuraType.PeriodicDummy)
|
||||
break;
|
||||
|
||||
goto default;
|
||||
}
|
||||
default:
|
||||
{
|
||||
// No value and not interrupt cast or crowd control without SPELL_ATTR0_UNAFFECTED_BY_INVULNERABILITY flag
|
||||
if (effect.CalcValue() == 0 && !((effect.Effect == SpellEffectName.InterruptCast || spellInfo.HasAttribute(SpellCustomAttributes.AuraCC)) && !spellInfo.HasAttribute(SpellAttr0.UnaffectedByInvulnerability)))
|
||||
break;
|
||||
|
||||
// Sindragosa Frost Breath
|
||||
if (spellInfo.Id == 69649 || spellInfo.Id == 71056 || spellInfo.Id == 71057 || spellInfo.Id == 71058 || spellInfo.Id == 73061 || spellInfo.Id == 73062 || spellInfo.Id == 73063 || spellInfo.Id == 73064)
|
||||
break;
|
||||
|
||||
// Frostbolt
|
||||
if (spellInfo.SpellFamilyName == SpellFamilyNames.Mage && spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x20u))
|
||||
break;
|
||||
|
||||
// Frost Fever
|
||||
if (spellInfo.Id == 55095)
|
||||
break;
|
||||
|
||||
// Haunt
|
||||
if (spellInfo.SpellFamilyName == SpellFamilyNames.Warlock && spellInfo.SpellFamilyFlags[1].HasAnyFlag(0x40000u))
|
||||
break;
|
||||
|
||||
setFlag = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (setFlag)
|
||||
{
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.BinarySpell;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Remove normal school mask to properly calculate damage
|
||||
if (spellInfo.SchoolMask.HasAnyFlag(SpellSchoolMask.Normal) && spellInfo.SchoolMask.HasAnyFlag(SpellSchoolMask.Magic))
|
||||
{
|
||||
spellInfo.SchoolMask &= ~SpellSchoolMask.Normal;
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.SchoolmaskNormalWithMagic;
|
||||
}
|
||||
|
||||
if (!spellInfo._IsPositiveEffect(0, false))
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.NegativeEff0;
|
||||
|
||||
@@ -2244,9 +2335,67 @@ namespace Game.Entities
|
||||
if (talentSpells.Contains(spellInfo.Id))
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.IsTalent;
|
||||
|
||||
switch (spellInfo.SpellFamilyName)
|
||||
{
|
||||
case SpellFamilyNames.Warrior:
|
||||
// Shout / Piercing Howl
|
||||
if (spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x20000u)/* || spellInfo->SpellFamilyFlags[1] & 0x20*/)
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.AuraCC;
|
||||
break;
|
||||
case SpellFamilyNames.Druid:
|
||||
// Roar
|
||||
if (spellInfo.SpellFamilyFlags[0].HasAnyFlag(0x8u))
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.AuraCC;
|
||||
break;
|
||||
case SpellFamilyNames.Generic:
|
||||
// Stoneclaw Totem effect
|
||||
if (spellInfo.Id == 5729)
|
||||
spellInfo.AttributesCu |= SpellCustomAttributes.AuraCC;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
spellInfo._InitializeExplicitTargetMask();
|
||||
}
|
||||
|
||||
// addition for binary spells, ommit spells triggering other spells
|
||||
foreach (var spellInfo in mSpellInfoMap.Values)
|
||||
{
|
||||
if (spellInfo.HasAttribute(SpellCustomAttributes.BinarySpell))
|
||||
continue;
|
||||
|
||||
bool allNonBinary = true;
|
||||
bool overrideAttr = false;
|
||||
foreach (SpellEffectInfo effect in spellInfo.GetEffectsForDifficulty(Difficulty.None))
|
||||
{
|
||||
if (effect == null)
|
||||
continue;
|
||||
|
||||
if (effect.IsAura() && effect.TriggerSpell != 0)
|
||||
{
|
||||
switch (effect.ApplyAuraName)
|
||||
{
|
||||
case AuraType.PeriodicTriggerSpell:
|
||||
case AuraType.PeriodicTriggerSpellWithValue:
|
||||
SpellInfo triggerSpell = Global.SpellMgr.GetSpellInfo(effect.TriggerSpell);
|
||||
if (triggerSpell != null)
|
||||
{
|
||||
overrideAttr = true;
|
||||
if (triggerSpell.HasAttribute(SpellCustomAttributes.BinarySpell))
|
||||
allNonBinary = false;
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (overrideAttr && allNonBinary)
|
||||
spellInfo.AttributesCu &= ~SpellCustomAttributes.BinarySpell;
|
||||
}
|
||||
|
||||
Log.outInfo(LogFilter.ServerLoading, "Loaded spell custom attributes in {0} ms", Time.GetMSTimeDiffToNow(oldMSTime));
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user