Core/Auras: reworked multiplicative AuraEffects calculation

Port From (https://github.com/TrinityCore/TrinityCore/commit/ebc06b1d0401be69066986e18d0e926170c58023)
This commit is contained in:
hondacrx
2020-05-05 18:38:43 -04:00
parent 5a178644b5
commit 9ec956becf
15 changed files with 796 additions and 428 deletions
+67 -23
View File
@@ -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);
}
}
}
+2 -1
View File
@@ -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
+6 -9
View File
@@ -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;
}
+20 -19
View File
@@ -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;