Implemented binary resistances and some more

Port From (https://github.com/TrinityCore/TrinityCore/commit/ca26c33145cb40ae7fd2c84fc7577fc6f11bdbbf)
This commit is contained in:
hondacrx
2019-08-16 23:15:19 -04:00
parent d3bce6a75c
commit bdfea4ecad
8 changed files with 322 additions and 105 deletions
+79 -36
View File
@@ -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());
+68 -17
View File
@@ -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