Core/Auras: reworked multiplicative AuraEffects calculation
Port From (https://github.com/TrinityCore/TrinityCore/commit/ebc06b1d0401be69066986e18d0e926170c58023)
This commit is contained in:
@@ -1351,7 +1351,7 @@ namespace Game.Entities
|
||||
return;
|
||||
|
||||
if (PvP)
|
||||
{
|
||||
{
|
||||
combatTimer = 5000;
|
||||
Player me = ToPlayer();
|
||||
if (me)
|
||||
@@ -2146,17 +2146,16 @@ namespace Game.Entities
|
||||
return MeleeHitOutcome.Normal;
|
||||
}
|
||||
public uint CalculateDamage(WeaponAttackType attType, bool normalized, bool addTotalPct)
|
||||
{
|
||||
float minDamage, maxDamage = 0.0f;
|
||||
{
|
||||
float minDamage;
|
||||
float maxDamage;
|
||||
|
||||
if (normalized || !addTotalPct)
|
||||
{
|
||||
CalculateMinMaxDamage(attType, normalized, addTotalPct, out minDamage, out maxDamage);
|
||||
if (IsInFeralForm() && attType == WeaponAttackType.BaseAttack)
|
||||
{
|
||||
float minOffhandDamage = 0.0f;
|
||||
float maxOffhandDamage = 0.0f;
|
||||
CalculateMinMaxDamage(WeaponAttackType.OffAttack, normalized, addTotalPct, out minOffhandDamage, out maxOffhandDamage);
|
||||
CalculateMinMaxDamage(WeaponAttackType.OffAttack, normalized, addTotalPct, out float minOffhandDamage, out float maxOffhandDamage);
|
||||
minDamage += minOffhandDamage;
|
||||
maxDamage += maxOffhandDamage;
|
||||
}
|
||||
@@ -2266,19 +2265,6 @@ namespace Game.Entities
|
||||
return ap * (1.0f + m_unitData.AttackPowerMultiplier);
|
||||
}
|
||||
}
|
||||
public float GetModifierValue(UnitMods unitMod, UnitModifierType modifierType)
|
||||
{
|
||||
if (unitMod >= UnitMods.End || modifierType >= UnitModifierType.End)
|
||||
{
|
||||
Log.outError(LogFilter.Unit, "attempt to access non-existing modifier value from UnitMods!");
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (modifierType == UnitModifierType.TotalPCT && m_auraModifiersGroup[(int)unitMod][(int)modifierType] <= 0.0f)
|
||||
return 0.0f;
|
||||
|
||||
return m_auraModifiersGroup[(int)unitMod][(int)modifierType];
|
||||
}
|
||||
public bool IsWithinMeleeRange(Unit obj)
|
||||
{
|
||||
if (!obj || !IsInMap(obj) || !IsInPhase(obj))
|
||||
@@ -2449,7 +2435,7 @@ namespace Game.Entities
|
||||
uint bossLevel = 83;
|
||||
float bossResistanceConstant = 510.0f;
|
||||
uint level = victim.GetLevelForTarget(this);
|
||||
float resistanceConstant = 0.0f;
|
||||
float resistanceConstant;
|
||||
|
||||
if (level == bossLevel)
|
||||
resistanceConstant = bossResistanceConstant;
|
||||
@@ -2492,7 +2478,7 @@ namespace Game.Entities
|
||||
vSchoolAbsorbCopy.Sort(new AbsorbAuraOrderPred());
|
||||
|
||||
// absorb without mana cost
|
||||
for (var i = 0; i < vSchoolAbsorbCopy.Count; ++i )
|
||||
for (var i = 0; i < vSchoolAbsorbCopy.Count; ++i)
|
||||
{
|
||||
var absorbAurEff = vSchoolAbsorbCopy[i];
|
||||
if (damageInfo.GetDamage() == 0)
|
||||
@@ -2758,7 +2744,7 @@ namespace Game.Entities
|
||||
// no more than 100%
|
||||
MathFunctions.RoundToInterval(ref arpPct, 0.0f, 100.0f);
|
||||
|
||||
float maxArmorPen = 0.0f;
|
||||
float maxArmorPen;
|
||||
if (victim.GetLevelForTarget(attacker) < 60)
|
||||
maxArmorPen = 400 + 85 * victim.GetLevelForTarget(attacker);
|
||||
else
|
||||
@@ -3014,10 +3000,15 @@ namespace Game.Entities
|
||||
return (CastingTime / 3500.0f) * DotFactor;
|
||||
}
|
||||
|
||||
void ApplyPercentModFloatVar(ref float var, float val, bool apply)
|
||||
{
|
||||
var *= (apply ? (100.0f + val) / 100.0f : 100.0f / (100.0f + val));
|
||||
}
|
||||
|
||||
public void ApplyAttackTimePercentMod(WeaponAttackType att, float val, bool apply)
|
||||
{
|
||||
float remainingTimePct = m_attackTimer[(int)att] / (m_baseAttackSpeed[(int)att] * m_modAttackSpeedPct[(int)att]);
|
||||
if (val > 0)
|
||||
if (val > 0.0f)
|
||||
{
|
||||
MathFunctions.ApplyPercentModFloatVar(ref m_modAttackSpeedPct[(int)att], val, !apply);
|
||||
|
||||
@@ -3265,5 +3256,58 @@ namespace Game.Entities
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public virtual bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect aurEff) { return true; }
|
||||
|
||||
public virtual void UpdateDamageDoneMods(WeaponAttackType attackType)
|
||||
{
|
||||
UnitMods unitMod = attackType switch
|
||||
{
|
||||
WeaponAttackType.BaseAttack => UnitMods.DamageMainHand,
|
||||
WeaponAttackType.OffAttack => UnitMods.DamageOffHand,
|
||||
WeaponAttackType.RangedAttack => UnitMods.DamageRanged,
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
float amount = GetTotalAuraModifier(AuraType.ModDamageDone, auratype => CheckAttackFitToAuraRequirement(attackType, auratype));
|
||||
SetStatFlatModifier(unitMod, UnitModifierFlatType.Total, amount);
|
||||
}
|
||||
|
||||
public void UpdateAllDamageDoneMods()
|
||||
{
|
||||
for (var attackType = WeaponAttackType.BaseAttack; attackType < WeaponAttackType.Max; ++attackType)
|
||||
UpdateDamageDoneMods(attackType);
|
||||
}
|
||||
|
||||
public void UpdateDamagePctDoneMods(WeaponAttackType attackType)
|
||||
{
|
||||
(UnitMods unitMod, float factor) = attackType switch
|
||||
{
|
||||
WeaponAttackType.BaseAttack => (UnitMods.DamageMainHand, 1.0f),
|
||||
WeaponAttackType.OffAttack => (UnitMods.DamageOffHand, 0.5f),
|
||||
WeaponAttackType.RangedAttack => (UnitMods.DamageRanged, 1.0f),
|
||||
_ => throw new NotImplementedException(),
|
||||
};
|
||||
|
||||
factor *= GetTotalAuraMultiplier(AuraType.ModDamagePercentDone, aurEff =>
|
||||
{
|
||||
if (!aurEff.GetMiscValue().HasAnyFlag((int)SpellSchoolMask.Normal))
|
||||
return false;
|
||||
|
||||
return CheckAttackFitToAuraRequirement(attackType, aurEff);
|
||||
});
|
||||
|
||||
if (attackType == WeaponAttackType.OffAttack)
|
||||
factor *= GetTotalAuraMultiplier(AuraType.ModOffhandDamagePct, auraEffect => CheckAttackFitToAuraRequirement(attackType, auraEffect));
|
||||
|
||||
SetStatPctModifier(unitMod, UnitModifierPctType.Total, factor);
|
||||
}
|
||||
|
||||
public void UpdateAllDamagePctDoneMods()
|
||||
{
|
||||
for (var attackType = WeaponAttackType.BaseAttack; attackType < WeaponAttackType.Max; ++attackType)
|
||||
UpdateDamagePctDoneMods(attackType);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -103,7 +103,8 @@ namespace Game.Entities
|
||||
MultiMap<uint, AuraApplication> m_appliedAuras = new MultiMap<uint, AuraApplication>();
|
||||
MultiMap<uint, Aura> m_ownedAuras = new MultiMap<uint, Aura>();
|
||||
List<Aura> m_scAuras = new List<Aura>();
|
||||
protected float[][] m_auraModifiersGroup = new float[(int)UnitMods.End][];
|
||||
protected float[][] m_auraFlatModifiersGroup = new float[(int)UnitMods.End][];
|
||||
protected float[][] m_auraPctModifiersGroup = new float[(int)UnitMods.End][];
|
||||
uint m_removedAurasCount;
|
||||
|
||||
//General
|
||||
|
||||
@@ -951,7 +951,7 @@ namespace Game.Entities
|
||||
int levelBasedHitDiff = leveldif;
|
||||
|
||||
// Base hit chance from attacker and victim levels
|
||||
int modHitChance = 100;
|
||||
int modHitChance;
|
||||
if (levelBasedHitDiff >= 0)
|
||||
{
|
||||
if (!victim.IsTypeId(TypeId.Player))
|
||||
@@ -2294,7 +2294,7 @@ namespace Game.Entities
|
||||
|
||||
public void ApplyCastTimePercentMod(float val, bool apply)
|
||||
{
|
||||
if (val > 0)
|
||||
if (val > 0.0f)
|
||||
{
|
||||
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModCastingSpeed), val, !apply);
|
||||
ApplyPercentModUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModSpellHaste), val, !apply);
|
||||
@@ -4547,13 +4547,10 @@ namespace Game.Entities
|
||||
return 0.0f;
|
||||
}
|
||||
|
||||
if (m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.TotalPCT] <= 0.0f)
|
||||
return 0.0f;
|
||||
|
||||
float value = MathFunctions.CalculatePct(m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.BaseValue], Math.Max(m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.BasePCTExcludeCreate], -100.0f));
|
||||
value *= m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.BasePCT];
|
||||
value += m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.TotalValue];
|
||||
value *= m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.TotalPCT];
|
||||
float value = MathFunctions.CalculatePct(GetFlatModifierValue(unitMod, UnitModifierFlatType.Base), Math.Max(GetFlatModifierValue(unitMod, UnitModifierFlatType.BasePCTExcludeCreate), -100.0f));
|
||||
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
|
||||
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
|
||||
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@@ -57,9 +57,18 @@ namespace Game.Entities
|
||||
m_spellImmune[i] = new MultiMap<uint, uint>();
|
||||
|
||||
for (byte i = 0; i < (int)UnitMods.End; ++i)
|
||||
m_auraModifiersGroup[i] = new float[] { 0.0f, 100.0f, 1.0f, 0.0f, 1.0f };
|
||||
{
|
||||
m_auraFlatModifiersGroup[i] = new float[(int)UnitModifierFlatType.End];
|
||||
m_auraFlatModifiersGroup[i][(int)UnitModifierFlatType.Base] = 0.0f;
|
||||
m_auraFlatModifiersGroup[i][(int)UnitModifierFlatType.BasePCTExcludeCreate] = 100.0f;
|
||||
m_auraFlatModifiersGroup[i][(int)UnitModifierFlatType.Total] = 0.0f;
|
||||
|
||||
m_auraModifiersGroup[(int)UnitMods.DamageOffHand][(int)UnitModifierType.TotalPCT] = 0.5f;
|
||||
m_auraPctModifiersGroup[i] = new float[(int)UnitModifierPctType.End];
|
||||
m_auraPctModifiersGroup[i][(int)UnitModifierPctType.Base] = 1.0f;
|
||||
m_auraPctModifiersGroup[i][(int)UnitModifierPctType.Total] = 1.0f;
|
||||
}
|
||||
|
||||
m_auraPctModifiersGroup[(int)UnitMods.DamageOffHand][(int)UnitModifierPctType.Total] = 0.5f;
|
||||
|
||||
foreach (AuraType auraType in Enum.GetValues(typeof(AuraType)))
|
||||
m_modAuras[auraType] = new List<AuraEffect>();
|
||||
@@ -1239,7 +1248,7 @@ namespace Game.Entities
|
||||
else if (GetRace() == Race.Worgen)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 9);
|
||||
skinColor = (byte)RandomHelper.URand(0, 9);
|
||||
|
||||
// Male
|
||||
if (GetGender() == Gender.Male)
|
||||
@@ -1284,7 +1293,7 @@ namespace Game.Entities
|
||||
else if (GetRace() == Race.Tauren)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 20);
|
||||
skinColor = (byte)RandomHelper.URand(0, 20);
|
||||
|
||||
if (GetGender() == Gender.Male)
|
||||
{
|
||||
@@ -1393,7 +1402,7 @@ namespace Game.Entities
|
||||
else if (GetRace() == Race.Worgen)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 8);
|
||||
skinColor = (byte)RandomHelper.URand(0, 8);
|
||||
|
||||
// Male
|
||||
if (GetGender() == Gender.Male)
|
||||
@@ -1438,7 +1447,7 @@ namespace Game.Entities
|
||||
else if (GetRace() == Race.Tauren)
|
||||
{
|
||||
if (HasAura(210333)) // Glyph of the Feral Chameleon
|
||||
hairColor = (byte)RandomHelper.URand(0, 20);
|
||||
skinColor = (byte)RandomHelper.URand(0, 20);
|
||||
|
||||
if (GetGender() == Gender.Male)
|
||||
{
|
||||
@@ -1679,10 +1688,6 @@ namespace Game.Entities
|
||||
SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ShapeshiftForm), (byte)form);
|
||||
}
|
||||
|
||||
public void SetModifierValue(UnitMods unitMod, UnitModifierType modifierType, float value)
|
||||
{
|
||||
m_auraModifiersGroup[(int)unitMod][(int)modifierType] = value;
|
||||
}
|
||||
public int CalcSpellDuration(SpellInfo spellProto)
|
||||
{
|
||||
sbyte comboPoints = (sbyte)(m_playerMovingMe != null ? m_playerMovingMe.GetComboPoints() : 0);
|
||||
@@ -1932,20 +1937,16 @@ namespace Game.Entities
|
||||
FactionTemplateRecord entry = CliDB.FactionTemplateStorage.LookupByKey(GetFaction());
|
||||
if (entry == null)
|
||||
{
|
||||
ObjectGuid guid = ObjectGuid.Empty; // prevent repeating spam same faction problem
|
||||
|
||||
if (GetGUID() != guid)
|
||||
Player player = ToPlayer();
|
||||
if (player != null)
|
||||
Log.outError(LogFilter.Unit, "Player {0} has invalid faction (faction template id) #{1}", player.GetName(), GetFaction());
|
||||
else
|
||||
{
|
||||
Player player = ToPlayer();
|
||||
Creature creature = ToCreature();
|
||||
if (player != null)
|
||||
Log.outError(LogFilter.Unit, "Player {0} has invalid faction (faction template id) #{1}", player.GetName(), GetFaction());
|
||||
else if (creature != null)
|
||||
if (creature != null)
|
||||
Log.outError(LogFilter.Unit, "Creature (template id: {0}) has invalid faction (faction template id) #{1}", creature.GetCreatureTemplate().Entry, GetFaction());
|
||||
else
|
||||
Log.outError(LogFilter.Unit, "Unit (name={0}, type={1}) has invalid faction (faction template id) #{2}", GetName(), GetTypeId(), GetFaction());
|
||||
|
||||
guid = GetGUID();
|
||||
}
|
||||
}
|
||||
return entry;
|
||||
|
||||
Reference in New Issue
Block a user