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
+11 -7
View File
@@ -87,7 +87,7 @@ namespace Framework.Constants
public enum BaseModType
{
FlatMod,
PCTmod,
PctMod,
End
}
@@ -178,14 +178,18 @@ namespace Framework.Constants
PowerStart = Mana,
PowerEnd = Pain + 1
}
public enum UnitModifierType
public enum UnitModifierFlatType
{
BaseValue = 0,
Base = 0,
BasePCTExcludeCreate = 1, // percent modifier affecting all stat values from auras and gear but not player base for level
BasePCT = 2,
TotalValue = 3,
TotalPCT = 4,
End = 5
Total = 2,
End = 3
}
public enum UnitModifierPctType
{
Base = 0,
Total = 1,
End = 2
}
public enum VictimState
{
+14 -17
View File
@@ -312,12 +312,12 @@ namespace Game.Entities
UpdateLevelDependantStats(); // We still re-initialize level dependant stats on entry update
SetMeleeDamageSchool((SpellSchools)cInfo.DmgSchool);
SetModifierValue(UnitMods.ResistanceHoly, UnitModifierType.BaseValue, cInfo.Resistance[(int)SpellSchools.Holy]);
SetModifierValue(UnitMods.ResistanceFire, UnitModifierType.BaseValue, cInfo.Resistance[(int)SpellSchools.Fire]);
SetModifierValue(UnitMods.ResistanceNature, UnitModifierType.BaseValue, cInfo.Resistance[(int)SpellSchools.Nature]);
SetModifierValue(UnitMods.ResistanceFrost, UnitModifierType.BaseValue, cInfo.Resistance[(int)SpellSchools.Frost]);
SetModifierValue(UnitMods.ResistanceShadow, UnitModifierType.BaseValue, cInfo.Resistance[(int)SpellSchools.Shadow]);
SetModifierValue(UnitMods.ResistanceArcane, UnitModifierType.BaseValue, cInfo.Resistance[(int)SpellSchools.Arcane]);
SetStatFlatModifier(UnitMods.ResistanceHoly, UnitModifierFlatType.Base, cInfo.Resistance[(int)SpellSchools.Holy]);
SetStatFlatModifier(UnitMods.ResistanceFire, UnitModifierFlatType.Base, cInfo.Resistance[(int)SpellSchools.Fire]);
SetStatFlatModifier(UnitMods.ResistanceNature, UnitModifierFlatType.Base, cInfo.Resistance[(int)SpellSchools.Nature]);
SetStatFlatModifier(UnitMods.ResistanceFrost, UnitModifierFlatType.Base, cInfo.Resistance[(int)SpellSchools.Frost]);
SetStatFlatModifier(UnitMods.ResistanceShadow, UnitModifierFlatType.Base, cInfo.Resistance[(int)SpellSchools.Shadow]);
SetStatFlatModifier(UnitMods.ResistanceArcane, UnitModifierFlatType.Base, cInfo.Resistance[(int)SpellSchools.Arcane]);
SetCanModifyStats(true);
UpdateAllStats();
@@ -563,7 +563,7 @@ namespace Game.Entities
if (curValue >= maxValue)
return;
float addvalue = 0.0f;
float addvalue;
switch (power)
{
@@ -614,7 +614,7 @@ namespace Game.Entities
if (curValue >= maxValue)
return;
long addvalue = 0;
long addvalue;
// Not only pet, but any controlled creature (and not polymorphed)
if (!GetCharmerOrOwnerGUID().IsEmpty() && !IsPolymorphed())
@@ -1166,7 +1166,7 @@ namespace Game.Entities
break;
}
SetModifierValue(UnitMods.Health, UnitModifierType.BaseValue, health);
SetStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Base, health);
//Damage
float basedamage = stats.GenerateBaseDamage(cInfo);
@@ -1182,11 +1182,11 @@ namespace Game.Entities
SetBaseWeaponDamage(WeaponAttackType.RangedAttack, WeaponDamageRange.MinDamage, weaponBaseMinDamage);
SetBaseWeaponDamage(WeaponAttackType.RangedAttack, WeaponDamageRange.MaxDamage, weaponBaseMaxDamage);
SetModifierValue(UnitMods.AttackPower, UnitModifierType.BaseValue, stats.AttackPower);
SetModifierValue(UnitMods.AttackPowerRanged, UnitModifierType.BaseValue, stats.RangedAttackPower);
SetStatFlatModifier(UnitMods.AttackPower, UnitModifierFlatType.Base, stats.AttackPower);
SetStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Base, stats.RangedAttackPower);
float armor = stats.GenerateArmor(cInfo); // @todo Why is this treated as uint32 when it's a float?
SetModifierValue(UnitMods.Armor, UnitModifierType.BaseValue, armor);
SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, armor);
}
float _GetHealthMod(CreatureEliteType Rank)
@@ -2026,7 +2026,6 @@ namespace Game.Entities
return false;
}
Unit myVictim = GetAttackerForHelper();
Unit targetVictim = target.GetAttackerForHelper();
// if I'm already fighting target, or I'm hostile towards the target, the target is acceptable
@@ -2263,13 +2262,11 @@ namespace Game.Entities
public void GetRespawnPosition(out float x, out float y, out float z)
{
float notUsed;
GetRespawnPosition(out x, out y, out z, out notUsed, out notUsed);
GetRespawnPosition(out x, out y, out z, out _, out _);
}
public void GetRespawnPosition(out float x, out float y, out float z, out float ori)
{
float notUsed;
GetRespawnPosition(out x, out y, out z, out ori, out notUsed);
GetRespawnPosition(out x, out y, out z, out ori, out _);
}
public void GetRespawnPosition(out float x, out float y, out float z, out float ori, out float dist)
{
+1 -6
View File
@@ -157,7 +157,7 @@ namespace Game.Entities
return;
// @todo research if talents/effects that increase total agility by x% should increase non-diminishing part
float base_agility = GetCreateStat(Stats.Agility) * m_auraModifiersGroup[(int)UnitMods.StatAgility][(int)UnitModifierType.BasePCT];
float base_agility = GetCreateStat(Stats.Agility) * GetPctModifierValue(UnitMods(UNIT_MOD_STAT_START + STAT_AGILITY), BASE_PCT);
float bonus_agility = GetStat(Stats.Agility) - base_agility;
// calculate diminishing (green in char screen) and non-diminishing (white) contribution
@@ -166,11 +166,6 @@ namespace Game.Entities
*/
}
float GetTotalPercentageModValue(BaseModGroup modGroup)
{
return m_auraBaseMod[(int)modGroup][0] + m_auraBaseMod[(int)modGroup][1];
}
public float GetExpertiseDodgeOrParryReduction(WeaponAttackType attType)
{
float baseExpertise = 7.5f;
+2 -1
View File
@@ -141,7 +141,8 @@ namespace Game.Entities
//Combat
int[] baseRatingValue = new int[(int)CombatRating.Max];
public float[][] m_auraBaseMod = new float[(int)BaseModGroup.End][];
float[] m_auraBaseFlatMod = new float[(int)BaseModGroup.End];
float[] m_auraBasePctMod = new float[(int)BaseModGroup.End];
public DuelInfo duel;
bool m_canParry;
bool m_canBlock;
+56 -51
View File
@@ -1098,8 +1098,7 @@ namespace Game.Entities
}
public InventoryResult CanStoreNewItem(byte bag, byte slot, List<ItemPosCount> dest, uint item, uint count)
{
uint notused;
return CanStoreItem(bag, slot, dest, item, count, null, false, out notused);
return CanStoreItem(bag, slot, dest, item, count, null, false, out _);
}
Item _StoreItem(ushort pos, Item pItem, uint count, bool clone, bool update)
@@ -1233,8 +1232,7 @@ namespace Game.Entities
// attempt equip by one
while (titem_amount > 0)
{
ushort eDest = 0;
msg = CanEquipNewItem(ItemConst.NullSlot, out eDest, titem_id, false);
msg = CanEquipNewItem(ItemConst.NullSlot, out ushort eDest, titem_id, false);
if (msg != InventoryResult.Ok)
break;
@@ -1890,7 +1888,7 @@ namespace Game.Entities
//Add/Remove/Misc Item
public bool AddItem(uint itemId, uint count)
{
uint noSpaceForCount = 0;
uint noSpaceForCount;
List<ItemPosCount> dest = new List<ItemPosCount>();
InventoryResult msg = CanStoreNewItem(ItemConst.NullBag, ItemConst.NullSlot, dest, itemId, count, out noSpaceForCount);
if (msg != InventoryResult.Ok)
@@ -3525,7 +3523,7 @@ namespace Game.Entities
}
uint stacks = count / crItem.maxcount;
ItemExtendedCostRecord iece = null;
ItemExtendedCostRecord iece;
if (crItem.ExtendedCost != 0)
{
iece = CliDB.ItemExtendedCostStorage.LookupByKey(crItem.ExtendedCost);
@@ -3991,8 +3989,15 @@ namespace Game.Entities
_ApplyItemBonuses(item, slot, apply);
ApplyItemEquipSpell(item, apply);
if (updateItemAuras)
{
ApplyItemDependentAuras(item, apply);
WeaponAttackType attackType = Player.GetAttackBySlot(slot, item.GetTemplate().GetInventoryType());
if (attackType != WeaponAttackType.Max)
UpdateWeaponDependentAuras(attackType);
}
ApplyArtifactPowers(item, apply);
ApplyAzeritePowers(item, apply);
ApplyEnchantment(item, apply);
@@ -4025,22 +4030,22 @@ namespace Game.Entities
switch ((ItemModType)statType)
{
case ItemModType.Mana:
HandleStatModifier(UnitMods.Mana, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.Mana, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.Health: // modify HP
HandleStatModifier(UnitMods.Health, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.Agility: // modify agility
HandleStatModifier(UnitMods.StatAgility, UnitModifierType.BaseValue, (float)val, apply);
ApplyStatBuffMod(Stats.Agility, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatAgility, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatAgility, UnitModifierFlatType.Base, (float)val, apply);
UpdateStatBuffMod(Stats.Agility);
break;
case ItemModType.Strength: //modify strength
HandleStatModifier(UnitMods.StatStrength, UnitModifierType.BaseValue, (float)val, apply);
ApplyStatBuffMod(Stats.Strength, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatStrength, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatStrength, UnitModifierFlatType.Base, (float)val, apply);
UpdateStatBuffMod(Stats.Strength);
break;
case ItemModType.Intellect: //modify intellect
HandleStatModifier(UnitMods.StatIntellect, UnitModifierType.BaseValue, (float)val, apply);
ApplyStatBuffMod(Stats.Intellect, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatIntellect, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatIntellect, UnitModifierFlatType.Base, (float)val, apply);
UpdateStatBuffMod(Stats.Intellect);
break;
//case ItemModType.Spirit: //modify spirit
//HandleStatModifier(UnitMods.StatSpirit, UnitModifierType.BaseValue, (float)val, apply);
@@ -4051,8 +4056,8 @@ namespace Game.Entities
if (staminaMult != null)
val = (int)(val * CliDB.GetIlvlStatMultiplier(staminaMult, proto.GetInventoryType()));
HandleStatModifier(UnitMods.StatStamina, UnitModifierType.BaseValue, (float)val, apply);
ApplyStatBuffMod(Stats.Stamina, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatStamina, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatStamina, UnitModifierFlatType.Base, (float)val, apply);
UpdateStatBuffMod(Stats.Stamina);
break;
case ItemModType.DefenseSkillRating:
ApplyRatingMod(CombatRating.DefenseSkill, (int)(val * combatRatingMultiplier), apply);
@@ -4118,11 +4123,11 @@ namespace Game.Entities
ApplyRatingMod(CombatRating.Expertise, (int)(val * combatRatingMultiplier), apply);
break;
case ItemModType.AttackPower:
HandleStatModifier(UnitMods.AttackPower, UnitModifierType.TotalValue, (float)val, apply);
HandleStatModifier(UnitMods.AttackPowerRanged, UnitModifierType.TotalValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.AttackPower, UnitModifierFlatType.Total, (float)val, apply);
HandleStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Total, (float)val, apply);
break;
case ItemModType.RangedAttackPower:
HandleStatModifier(UnitMods.AttackPowerRanged, UnitModifierType.TotalValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Total, (float)val, apply);
break;
case ItemModType.Versatility:
ApplyRatingMod(CombatRating.VersatilityDamageDone, (int)(val * combatRatingMultiplier), apply);
@@ -4148,25 +4153,25 @@ namespace Game.Entities
ApplyRatingMod(CombatRating.Mastery, (int)(val * combatRatingMultiplier), apply);
break;
case ItemModType.ExtraArmor:
HandleStatModifier(UnitMods.Armor, UnitModifierType.TotalValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Total, (float)val, apply);
break;
case ItemModType.FireResistance:
HandleStatModifier(UnitMods.ResistanceFire, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.ResistanceFire, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.FrostResistance:
HandleStatModifier(UnitMods.ResistanceFrost, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.ResistanceFrost, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.HolyResistance:
HandleStatModifier(UnitMods.ResistanceHoly, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.ResistanceHoly, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.ShadowResistance:
HandleStatModifier(UnitMods.ResistanceShadow, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.ResistanceShadow, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.NatureResistance:
HandleStatModifier(UnitMods.ResistanceNature, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.ResistanceNature, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.ArcaneResistance:
HandleStatModifier(UnitMods.ResistanceArcane, UnitModifierType.BaseValue, (float)val, apply);
HandleStatFlatModifier(UnitMods.ResistanceArcane, UnitModifierFlatType.Base, (float)val, apply);
break;
case ItemModType.PvpPower:
ApplyRatingMod(CombatRating.PvpPower, val, apply);
@@ -4202,37 +4207,37 @@ namespace Game.Entities
ApplyRatingMod(CombatRating.Unused12, val, apply);
break;
case ItemModType.AgiStrInt:
HandleStatModifier(UnitMods.StatAgility, UnitModifierType.BaseValue, val, apply);
HandleStatModifier(UnitMods.StatStrength, UnitModifierType.BaseValue, val, apply);
HandleStatModifier(UnitMods.StatIntellect, UnitModifierType.BaseValue, val, apply);
ApplyStatBuffMod(Stats.Agility, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatAgility, UnitModifierType.BasePCTExcludeCreate)), apply);
ApplyStatBuffMod(Stats.Strength, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatStrength, UnitModifierType.BasePCTExcludeCreate)), apply);
ApplyStatBuffMod(Stats.Intellect, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatIntellect, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatAgility, UnitModifierFlatType.Base, val, apply);
HandleStatFlatModifier(UnitMods.StatStrength, UnitModifierFlatType.Base, val, apply);
HandleStatFlatModifier(UnitMods.StatIntellect, UnitModifierFlatType.Base, val, apply);
UpdateStatBuffMod(Stats.Agility);
UpdateStatBuffMod(Stats.Strength);
UpdateStatBuffMod(Stats.Intellect);
break;
case ItemModType.AgiStr:
HandleStatModifier(UnitMods.StatAgility, UnitModifierType.BaseValue, val, apply);
HandleStatModifier(UnitMods.StatStrength, UnitModifierType.BaseValue, val, apply);
ApplyStatBuffMod(Stats.Agility, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatAgility, UnitModifierType.BasePCTExcludeCreate)), apply);
ApplyStatBuffMod(Stats.Strength, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatStrength, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatAgility, UnitModifierFlatType.Base, val, apply);
HandleStatFlatModifier(UnitMods.StatStrength, UnitModifierFlatType.Base, val, apply);
UpdateStatBuffMod(Stats.Agility);
UpdateStatBuffMod(Stats.Strength);
break;
case ItemModType.AgiInt:
HandleStatModifier(UnitMods.StatAgility, UnitModifierType.BaseValue, val, apply);
HandleStatModifier(UnitMods.StatIntellect, UnitModifierType.BaseValue, val, apply);
ApplyStatBuffMod(Stats.Agility, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatAgility, UnitModifierType.BasePCTExcludeCreate)), apply);
ApplyStatBuffMod(Stats.Intellect, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatIntellect, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatAgility, UnitModifierFlatType.Base, val, apply);
HandleStatFlatModifier(UnitMods.StatIntellect, UnitModifierFlatType.Base, val, apply);
UpdateStatBuffMod(Stats.Agility);
UpdateStatBuffMod(Stats.Intellect);
break;
case ItemModType.StrInt:
HandleStatModifier(UnitMods.StatStrength, UnitModifierType.BaseValue, val, apply);
HandleStatModifier(UnitMods.StatIntellect, UnitModifierType.BaseValue, val, apply);
ApplyStatBuffMod(Stats.Strength, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatStrength, UnitModifierType.BasePCTExcludeCreate)), apply);
ApplyStatBuffMod(Stats.Intellect, MathFunctions.CalculatePct(val, GetModifierValue(UnitMods.StatIntellect, UnitModifierType.BasePCTExcludeCreate)), apply);
HandleStatFlatModifier(UnitMods.StatStrength, UnitModifierFlatType.Base, val, apply);
HandleStatFlatModifier(UnitMods.StatIntellect, UnitModifierFlatType.Base, val, apply);
UpdateStatBuffMod(Stats.Strength);
UpdateStatBuffMod(Stats.Intellect);
break;
}
}
uint armor = item.GetArmor(this);
if (armor != 0)
HandleStatModifier(UnitMods.Armor, UnitModifierType.BaseValue, (float)armor, apply);
HandleStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, (float)armor, apply);
WeaponAttackType attType = WeaponAttackType.BaseAttack;
if (slot == EquipmentSlot.MainHand && (proto.GetInventoryType() == InventoryType.Ranged || proto.GetInventoryType() == InventoryType.RangedRight))
@@ -4425,6 +4430,10 @@ namespace Game.Entities
ApplyItemDependentAuras(m_items[i], true);
_ApplyItemBonuses(m_items[i], i, true);
WeaponAttackType attackType = Player.GetAttackBySlot(i, m_items[i].GetTemplate().GetInventoryType());
if (attackType != WeaponAttackType.Max)
UpdateWeaponDependentAuras(attackType);
}
}
@@ -6229,11 +6238,7 @@ namespace Game.Entities
public void SetLootGUID(ObjectGuid guid) { SetUpdateFieldValue(m_values.ModifyValue(m_playerData).ModifyValue(m_playerData.LootTargetGUID), guid); }
public void StoreLootItem(byte lootSlot, Loot loot, AELootResult aeResult = null)
{
NotNormalLootItem qitem = null;
NotNormalLootItem ffaitem = null;
NotNormalLootItem conditem = null;
LootItem item = loot.LootItemInSlot(lootSlot, this, out qitem, out ffaitem, out conditem);
LootItem item = loot.LootItemInSlot(lootSlot, this, out NotNormalLootItem qitem, out NotNormalLootItem ffaitem, out NotNormalLootItem conditem);
if (item == null)
{
SendEquipError(InventoryResult.LootGone);
@@ -6385,7 +6390,7 @@ namespace Game.Entities
if (!currentLootGuid.IsEmpty() && !aeLooting)
Session.DoLootRelease(currentLootGuid);
Loot loot = null;
Loot loot;
PermissionTypes permission = PermissionTypes.All;
Log.outDebug(LogFilter.Loot, "Player.SendLoot");
+78 -41
View File
@@ -153,9 +153,6 @@ namespace Game.Entities
if (skillStatusData == null || skillStatusData.State == SkillState.Deleted || skillInfo.SkillRank[skillStatusData.Pos] == 0)
return 0;
var field = (ushort)(skillStatusData.Pos / 2);
var offset = (byte)(skillStatusData.Pos & 1);
return skillInfo.SkillStep[skillStatusData.Pos];
}
@@ -613,15 +610,11 @@ namespace Game.Entities
// processed in Player.CastItemCombatSpell
break;
case ItemEnchantmentType.Damage:
if (item.GetSlot() == EquipmentSlot.MainHand)
{
if (item.GetTemplate().GetInventoryType() != InventoryType.Ranged && item.GetTemplate().GetInventoryType() != InventoryType.RangedRight)
HandleStatModifier(UnitMods.DamageMainHand, UnitModifierType.TotalValue, enchant_amount, apply);
else
HandleStatModifier(UnitMods.DamageRanged, UnitModifierType.TotalValue, enchant_amount, apply);
WeaponAttackType attackType = Player.GetAttackBySlot(item.GetSlot(), item.GetTemplate().GetInventoryType());
if (attackType != WeaponAttackType.Max)
UpdateDamageDoneMods(attackType);
}
else if (item.GetSlot() == EquipmentSlot.OffHand)
HandleStatModifier(UnitMods.DamageOffHand, UnitModifierType.TotalValue, enchant_amount, apply);
break;
case ItemEnchantmentType.EquipSpell:
if (enchant_spell_id != 0)
@@ -654,7 +647,7 @@ namespace Game.Entities
}
enchant_amount = Math.Max(enchant_amount, 1u);
HandleStatModifier((UnitMods)((uint)UnitMods.ResistanceStart + enchant_spell_id), UnitModifierType.TotalValue, enchant_amount, apply);
HandleStatFlatModifier((UnitMods)((uint)UnitMods.ResistanceStart + enchant_spell_id), UnitModifierFlatType.Total, enchant_amount, apply);
break;
case ItemEnchantmentType.Stat:
{
@@ -685,26 +678,26 @@ namespace Game.Entities
{
case ItemModType.Mana:
Log.outDebug(LogFilter.Player, "+ {0} MANA", enchant_amount);
HandleStatModifier(UnitMods.Mana, UnitModifierType.BaseValue, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.Mana, UnitModifierFlatType.Base, enchant_amount, apply);
break;
case ItemModType.Health:
Log.outDebug(LogFilter.Player, "+ {0} HEALTH", enchant_amount);
HandleStatModifier(UnitMods.Health, UnitModifierType.BaseValue, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Base, enchant_amount, apply);
break;
case ItemModType.Agility:
Log.outDebug(LogFilter.Player, "+ {0} AGILITY", enchant_amount);
HandleStatModifier(UnitMods.StatAgility, UnitModifierType.TotalValue, enchant_amount, apply);
ApplyStatBuffMod(Stats.Agility, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.StatAgility, UnitModifierFlatType.Total, enchant_amount, apply);
UpdateStatBuffMod(Stats.Agility);
break;
case ItemModType.Strength:
Log.outDebug(LogFilter.Player, "+ {0} STRENGTH", enchant_amount);
HandleStatModifier(UnitMods.StatStrength, UnitModifierType.TotalValue, enchant_amount, apply);
ApplyStatBuffMod(Stats.Strength, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.StatStrength, UnitModifierFlatType.Total, enchant_amount, apply);
UpdateStatBuffMod(Stats.Strength);
break;
case ItemModType.Intellect:
Log.outDebug(LogFilter.Player, "+ {0} INTELLECT", enchant_amount);
HandleStatModifier(UnitMods.StatIntellect, UnitModifierType.TotalValue, enchant_amount, apply);
ApplyStatBuffMod(Stats.Intellect, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.StatIntellect, UnitModifierFlatType.Total, enchant_amount, apply);
UpdateStatBuffMod(Stats.Intellect);
break;
//case ItemModType.Spirit:
//Log.outDebug(LogFilter.Player, "+ {0} SPIRIT", enchant_amount);
@@ -713,8 +706,8 @@ namespace Game.Entities
//break;
case ItemModType.Stamina:
Log.outDebug(LogFilter.Player, "+ {0} STAMINA", enchant_amount);
HandleStatModifier(UnitMods.StatStamina, UnitModifierType.TotalValue, enchant_amount, apply);
ApplyStatBuffMod(Stats.Stamina, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.StatStamina, UnitModifierFlatType.Total, enchant_amount, apply);
UpdateStatBuffMod(Stats.Stamina);
break;
case ItemModType.DefenseSkillRating:
ApplyRatingMod(CombatRating.DefenseSkill, (int)enchant_amount, apply);
@@ -786,12 +779,12 @@ namespace Game.Entities
Log.outDebug(LogFilter.Player, "+ {0} EXPERTISE", enchant_amount);
break;
case ItemModType.AttackPower:
HandleStatModifier(UnitMods.AttackPower, UnitModifierType.TotalValue, enchant_amount, apply);
HandleStatModifier(UnitMods.AttackPowerRanged, UnitModifierType.TotalValue, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.AttackPower, UnitModifierFlatType.Total, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Total, enchant_amount, apply);
Log.outDebug(LogFilter.Player, "+ {0} ATTACK_POWER", enchant_amount);
break;
case ItemModType.RangedAttackPower:
HandleStatModifier(UnitMods.AttackPowerRanged, UnitModifierType.TotalValue, enchant_amount, apply);
HandleStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Total, enchant_amount, apply);
Log.outDebug(LogFilter.Player, "+ {0} RANGED_ATTACK_POWER", enchant_amount);
break;
case ItemModType.ManaRegeneration:
@@ -815,7 +808,7 @@ namespace Game.Entities
Log.outDebug(LogFilter.Player, "+ {0} SPELL_PENETRATION", enchant_amount);
break;
case ItemModType.BlockValue:
HandleBaseModValue(BaseModGroup.ShieldBlockValue, BaseModType.FlatMod, enchant_amount, apply);
HandleBaseModFlatValue(BaseModGroup.ShieldBlockValue, enchant_amount, apply);
Log.outDebug(LogFilter.Player, "+ {0} BLOCK_VALUE", enchant_amount);
break;
case ItemModType.MasteryRating:
@@ -835,20 +828,9 @@ namespace Game.Entities
}
case ItemEnchantmentType.Totem: // Shaman Rockbiter Weapon
{
if (GetClass() == Class.Shaman)
{
float addValue = 0.0f;
if (item.GetSlot() == EquipmentSlot.MainHand)
{
addValue = enchant_amount * item.GetTemplate().GetDelay() / 1000.0f;
HandleStatModifier(UnitMods.DamageMainHand, UnitModifierType.TotalValue, addValue, apply);
}
else if (item.GetSlot() == EquipmentSlot.OffHand)
{
addValue = enchant_amount * item.GetTemplate().GetDelay() / 1000.0f;
HandleStatModifier(UnitMods.DamageOffHand, UnitModifierType.TotalValue, addValue, apply);
}
}
WeaponAttackType attackType = Player.GetAttackBySlot(item.GetSlot(), item.GetTemplate().GetInventoryType());
if (attackType != WeaponAttackType.Max)
UpdateDamageDoneMods(attackType);
break;
}
case ItemEnchantmentType.UseSpell:
@@ -1187,14 +1169,14 @@ namespace Game.Entities
if (skillSlot == 0)
{
Log.outError(LogFilter.Misc, $"Tried to add skill {id} but player {GetName()} ({GetGUID().ToString()}) cannot have additional skills");
Log.outError(LogFilter.Misc, $"Tried to add skill {id} but player {GetName()} ({GetGUID()}) cannot have additional skills");
return;
}
SkillLineRecord skillEntry = CliDB.SkillLineStorage.LookupByKey(id);
if (skillEntry == null)
{
Log.outError(LogFilter.Misc, $"Player.SetSkill: Skill (SkillID: {id}) not found in SkillLineStore for player '{GetName()}' ({GetGUID().ToString()})");
Log.outError(LogFilter.Misc, $"Player.SetSkill: Skill (SkillID: {id}) not found in SkillLineStore for player '{GetName()}' ({GetGUID()})");
return;
}
@@ -1829,6 +1811,48 @@ namespace Game.Entities
}
}
// this one rechecks weapon auras and stores them in BaseModGroup container
// needed for things like axe specialization applying only to axe weapons in case of dual-wield
void UpdateWeaponDependentCritAuras(WeaponAttackType attackType)
{
BaseModGroup modGroup;
switch (attackType)
{
case WeaponAttackType.BaseAttack:
modGroup = BaseModGroup.CritPercentage;
break;
case WeaponAttackType.OffAttack:
modGroup = BaseModGroup.OffhandCritPercentage;
break;
case WeaponAttackType.RangedAttack:
modGroup = BaseModGroup.RangedCritPercentage;
break;
default:
return;
}
float amount = 0.0f;
amount += GetTotalAuraModifier(AuraType.ModWeaponCritPercent, auraEffect => CheckAttackFitToAuraRequirement(attackType, auraEffect));
// these auras don't have item requirement (only Combat Expertise in 3.3.5a)
amount += GetTotalAuraModifier(AuraType.ModCritPct);
SetBaseModFlatValue(modGroup, amount);
}
public void UpdateAllWeaponDependentCritAuras()
{
for (var attackType = WeaponAttackType.BaseAttack; attackType < WeaponAttackType.Max; ++attackType)
UpdateWeaponDependentCritAuras(attackType);
}
public void UpdateWeaponDependentAuras(WeaponAttackType attackType)
{
UpdateWeaponDependentCritAuras(attackType);
UpdateDamageDoneMods(attackType);
UpdateDamagePctDoneMods(attackType);
}
public void ApplyItemDependentAuras(Item item, bool apply)
{
if (apply)
@@ -1851,6 +1875,19 @@ namespace Game.Entities
RemoveItemDependentAurasAndCasts(item);
}
public override bool CheckAttackFitToAuraRequirement(WeaponAttackType attackType, AuraEffect aurEff)
{
SpellInfo spellInfo = aurEff.GetSpellInfo();
if (spellInfo.EquippedItemClass == ItemClass.None)
return true;
Item item = GetWeaponForAttack(attackType, true);
if (item == null || !item.IsFitToSpellRequirements(spellInfo))
return false;
return true;
}
public void AddTemporarySpell(uint spellId)
{
var spell = m_spells.LookupByKey(spellId);
+116 -24
View File
@@ -83,7 +83,10 @@ namespace Game.Entities
_specializationInfo = new SpecializationInfo();
for (byte i = 0; i < (byte)BaseModGroup.End; ++i)
m_auraBaseMod[i] = new float[] { 0.0f, 1.0f };
{
m_auraBaseFlatMod[i] = 0.0f;
m_auraBasePctMod[i] = 1.0f;
}
for (var i = 0; i < (int)SpellModOp.Max; ++i)
{
@@ -3791,7 +3794,7 @@ namespace Game.Entities
if (powerType == null)
return;
float addvalue = 0.0f;
float addvalue;
if (!IsInCombat())
{
@@ -4695,7 +4698,7 @@ namespace Game.Entities
SpawnCorpseBones();
}
WorldSafeLocsEntry ClosestGrave = null;
WorldSafeLocsEntry ClosestGrave;
// Special handle for Battlegroundmaps
Battleground bg = GetBattleground();
@@ -5333,8 +5336,7 @@ namespace Game.Entities
PlayerLevelInfo info = Global.ObjectMgr.GetPlayerLevelInfo(GetRace(), GetClass(), level);
uint basemana = 0;
Global.ObjectMgr.GetPlayerClassLevelInfo(GetClass(), level, out basemana);
Global.ObjectMgr.GetPlayerClassLevelInfo(GetClass(), level, out uint basemana);
LevelUpInfo packet = new LevelUpInfo();
packet.Level = level;
@@ -6567,7 +6569,7 @@ namespace Game.Entities
if (level >= WorldConfig.GetIntValue(WorldCfg.MaxPlayerLevel))
return;
uint bonus_xp = 0;
uint bonus_xp;
bool recruitAFriend = GetsRecruitAFriendBonus(true);
// RaF does NOT stack with rested experience
@@ -6603,36 +6605,104 @@ namespace Game.Entities
SetXP(newXP);
}
public void HandleBaseModValue(BaseModGroup modGroup, BaseModType modType, float amount, bool apply)
public void HandleBaseModFlatValue(BaseModGroup modGroup, float amount, bool apply)
{
if (modGroup >= BaseModGroup.End || modType >= BaseModType.End)
if (modGroup >= BaseModGroup.End)
{
Log.outError(LogFilter.Spells, "ERROR in HandleBaseModValue(): non existed BaseModGroup of wrong BaseModType!");
Log.outError(LogFilter.Spells, $"Player.HandleBaseModFlatValue: Invalid BaseModGroup ({modGroup}) for player '{GetName()}' ({GetGUID()})");
return;
}
m_auraBaseFlatMod[(int)modGroup] += apply ? amount : -amount;
UpdateBaseModGroup(modGroup);
}
public void ApplyBaseModPctValue(BaseModGroup modGroup, float pct)
{
if (modGroup >= BaseModGroup.End)
{
Log.outError(LogFilter.Spells, $"Player.ApplyBaseModPctValue: Invalid BaseModGroup/BaseModType ({modGroup}/{BaseModType.FlatMod}) for player '{GetName()}' ({GetGUID()})");
return;
}
switch (modType)
MathFunctions.AddPct(ref m_auraBasePctMod[(int)modGroup], pct);
UpdateBaseModGroup(modGroup);
}
public void SetBaseModFlatValue(BaseModGroup modGroup, float val)
{
if (m_auraBaseFlatMod[(int)modGroup] == val)
return;
m_auraBaseFlatMod[(int)modGroup] = val;
UpdateBaseModGroup(modGroup);
}
public void SetBaseModPctValue(BaseModGroup modGroup, float val)
{
if (m_auraBasePctMod[(int)modGroup] == val)
return;
m_auraBasePctMod[(int)modGroup] = val;
UpdateBaseModGroup(modGroup);
}
public override void UpdateDamageDoneMods(WeaponAttackType attackType)
{
base.UpdateDamageDoneMods(attackType);
UnitMods unitMod = attackType switch
{
case BaseModType.FlatMod:
m_auraBaseMod[(int)modGroup][(int)modType] += apply ? amount : -amount;
break;
case BaseModType.PCTmod:
MathFunctions.ApplyPercentModFloatVar(ref m_auraBaseMod[(int)modGroup][(int)modType], amount, apply);
break;
WeaponAttackType.BaseAttack => UnitMods.DamageMainHand,
WeaponAttackType.OffAttack => UnitMods.DamageOffHand,
WeaponAttackType.RangedAttack => UnitMods.DamageRanged,
_ => throw new NotImplementedException(),
};
float amount = 0.0f;
Item item = GetWeaponForAttack(attackType, true);
if (item == null)
return;
for (var slot = EnchantmentSlot.Perm; slot < EnchantmentSlot.Max; ++slot)
{
SpellItemEnchantmentRecord enchantmentEntry = CliDB.SpellItemEnchantmentStorage.LookupByKey(item.GetEnchantmentId(slot));
if (enchantmentEntry == null)
continue;
for (byte i = 0; i < ItemConst.MaxItemEnchantmentEffects; ++i)
{
switch (enchantmentEntry.Effect[i])
{
case ItemEnchantmentType.Damage:
amount += enchantmentEntry.EffectScalingPoints[i];
break;
case ItemEnchantmentType.Totem:
if (GetClass() == Class.Shaman)
amount += enchantmentEntry.EffectScalingPoints[i] * item.GetTemplate().GetDelay() / 1000.0f;
break;
default:
break;
}
}
}
HandleStatFlatModifier(unitMod, UnitModifierFlatType.Total, amount, true);
}
void UpdateBaseModGroup(BaseModGroup modGroup)
{
if (!CanModifyStats())
return;
switch (modGroup)
{
case BaseModGroup.CritPercentage:
UpdateCritPercentage(WeaponAttackType.BaseAttack);
case BaseModGroup.CritPercentage:
UpdateCritPercentage(WeaponAttackType.BaseAttack);
break;
case BaseModGroup.RangedCritPercentage:
UpdateCritPercentage(WeaponAttackType.RangedAttack);
case BaseModGroup.RangedCritPercentage:
UpdateCritPercentage(WeaponAttackType.RangedAttack);
break;
case BaseModGroup.OffhandCritPercentage:
case BaseModGroup.OffhandCritPercentage:
UpdateCritPercentage(WeaponAttackType.OffAttack);
break;
default:
@@ -6640,6 +6710,28 @@ namespace Game.Entities
}
}
float GetBaseModValue(BaseModGroup modGroup, BaseModType modType)
{
if (modGroup >= BaseModGroup.End || modType >= BaseModType.End)
{
Log.outError(LogFilter.Spells, $"Player.GetBaseModValue: Invalid BaseModGroup/BaseModType ({modGroup}/{modType}) for player '{GetName()}' ({GetGUID()})");
return 0.0f;
}
return (modType == BaseModType.FlatMod ? m_auraBaseFlatMod[(int)modGroup] : m_auraBasePctMod[(int)modGroup]);
}
float GetTotalBaseModValue(BaseModGroup modGroup)
{
if (modGroup >= BaseModGroup.End)
{
Log.outError(LogFilter.Spells, $"Player.GetTotalBaseModValue: Invalid BaseModGroup ({modGroup}) for player '{GetName()}' ({GetGUID()})");
return 0.0f;
}
return m_auraBaseFlatMod[(int)modGroup] * m_auraBasePctMod[(int)modGroup];
}
public void AddComboPoints(sbyte count, Spell spell = null)
{
if (count == 0)
@@ -6898,7 +6990,7 @@ namespace Game.Entities
if (WorldConfig.GetBoolValue(WorldCfg.InstantTaxi))
{
var lastPathNode = CliDB.TaxiNodesStorage.LookupByKey(nodes[nodes.Count - 1]);
var lastPathNode = CliDB.TaxiNodesStorage.LookupByKey(nodes[^1]);
m_taxi.ClearTaxiDestinations();
ModifyMoney(-totalcost);
UpdateCriteria(CriteriaTypes.GoldSpentForTravelling, totalcost);
@@ -6956,7 +7048,7 @@ namespace Game.Entities
var nodeList = CliDB.TaxiPathNodesByPath[path];
float distPrev = MapConst.MapSize * MapConst.MapSize;
float distPrev;
float distNext = GetExactDistSq(nodeList[0].Loc.X, nodeList[0].Loc.Y, nodeList[0].Loc.Z);
for (int i = 1; i < nodeList.Length; ++i)
@@ -7277,7 +7369,7 @@ namespace Game.Entities
return null;
}
Item item = null;
Item item;
if (useable)
item = GetUseableItemByPos(InventorySlots.Bag0, slot);
else
+188 -78
View File
@@ -27,35 +27,99 @@ namespace Game.Entities
{
public partial class Unit
{
public bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, int amount, bool apply)
public void HandleStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float amount, bool apply)
{
return HandleStatModifier(unitMod, modifierType, (float)amount, apply);
}
public bool HandleStatModifier(UnitMods unitMod, UnitModifierType modifierType, float amount, bool apply)
{
if (unitMod >= UnitMods.End || modifierType >= UnitModifierType.End)
if (unitMod >= UnitMods.End || modifierType >= UnitModifierFlatType.End)
{
Log.outError(LogFilter.Unit, "ERROR in HandleStatModifier(): non-existing UnitMods or wrong UnitModifierType!");
return false;
Log.outError(LogFilter.Unit, "ERROR in HandleStatFlatModifier(): non-existing UnitMods or wrong UnitModifierFlatType!");
return;
}
if (amount == 0)
return;
switch (modifierType)
{
case UnitModifierType.BaseValue:
case UnitModifierType.BasePCTExcludeCreate:
case UnitModifierType.TotalValue:
m_auraModifiersGroup[(int)unitMod][(int)modifierType] += apply ? amount : -amount;
break;
case UnitModifierType.BasePCT:
case UnitModifierType.TotalPCT:
MathFunctions.ApplyPercentModFloatVar(ref m_auraModifiersGroup[(int)unitMod][(int)modifierType], amount, apply);
case UnitModifierFlatType.Base:
case UnitModifierFlatType.BasePCTExcludeCreate:
case UnitModifierFlatType.Total:
m_auraFlatModifiersGroup[(int)unitMod][(int)modifierType] += apply ? amount : -amount;
break;
default:
break;
}
UpdateUnitMod(unitMod);
}
public void ApplyStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float pct)
{
if (unitMod >= UnitMods.End || modifierType >= UnitModifierPctType.End)
{
Log.outError(LogFilter.Unit, "ERROR in ApplyStatPctModifier(): non-existing UnitMods or wrong UnitModifierPctType!");
return;
}
if (pct == 0)
return;
switch (modifierType)
{
case UnitModifierPctType.Base:
case UnitModifierPctType.Total:
MathFunctions.AddPct(ref m_auraPctModifiersGroup[(int)unitMod][(int)modifierType], pct);
break;
default:
break;
}
UpdateUnitMod(unitMod);
}
public void SetStatFlatModifier(UnitMods unitMod, UnitModifierFlatType modifierType, float val)
{
if (m_auraFlatModifiersGroup[(int)unitMod][(int)modifierType] == val)
return;
m_auraFlatModifiersGroup[(int)unitMod][(int)modifierType] = val;
UpdateUnitMod(unitMod);
}
public void SetStatPctModifier(UnitMods unitMod, UnitModifierPctType modifierType, float val)
{
if (m_auraPctModifiersGroup[(int)unitMod][(int)modifierType] == val)
return;
m_auraPctModifiersGroup[(int)unitMod][(int)modifierType] = val;
UpdateUnitMod(unitMod);
}
public float GetFlatModifierValue(UnitMods unitMod, UnitModifierFlatType modifierType)
{
if (unitMod >= UnitMods.End || modifierType >= UnitModifierFlatType.End)
{
Log.outError(LogFilter.Unit, "attempt to access non-existing modifier value from UnitMods!");
return 0.0f;
}
return m_auraFlatModifiersGroup[(int)unitMod][(int)modifierType];
}
public float GetPctModifierValue(UnitMods unitMod, UnitModifierPctType modifierType)
{
if (unitMod >= UnitMods.End || modifierType >= UnitModifierPctType.End)
{
Log.outError(LogFilter.Unit, "attempt to access non-existing modifier value from UnitMods!");
return 0.0f;
}
return m_auraPctModifiersGroup[(int)unitMod][(int)modifierType];
}
void UpdateUnitMod(UnitMods unitMod)
{
if (!CanModifyStats())
return false;
return;
switch (unitMod)
{
@@ -118,8 +182,6 @@ namespace Game.Entities
default:
break;
}
return true;
}
int GetMinPower(PowerType power) { return power == PowerType.LunarPower ? -100 : 0; }
@@ -181,16 +243,71 @@ namespace Game.Entities
return stat;
}
public void ApplyStatBuffMod(Stats stat, float val, bool apply)
public void UpdateStatBuffMod(Stats stat)
{
MathFunctions.ApplyPercentModFloatVar(ref (val > 0 ? ref m_floatStatPosBuff[(int)stat] : ref m_floatStatNegBuff[(int)stat]), val, apply);
float modPos = 0.0f;
float modNeg = 0.0f;
float factor = 0.0f;
UnitMods unitMod = UnitMods.StatStart + (int)stat;
// includes value from items and enchantments
float modValue = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base);
if (modValue > 0.0f)
modPos += modValue;
else
modNeg += modValue;
if (IsGuardian())
{
modValue = ((Guardian)this).GetBonusStatFromOwner(stat);
if (modValue > 0.0f)
modPos += modValue;
else
modNeg += modValue;
}
// SPELL_AURA_MOD_STAT_BONUS_PCT only affects BASE_VALUE
modPos = MathFunctions.CalculatePct(modPos, Math.Max(GetFlatModifierValue(unitMod, UnitModifierFlatType.BasePCTExcludeCreate), -100.0f));
modNeg = MathFunctions.CalculatePct(modPos, Math.Max(GetFlatModifierValue(unitMod, UnitModifierFlatType.BasePCTExcludeCreate), -100.0f));
modPos += GetTotalAuraModifier(AuraType.ModStat, aurEff =>
{
if ((aurEff.GetMiscValue() < 0 || aurEff.GetMiscValue() == (int)stat) && aurEff.GetAmount() > 0)
return true;
return false;
});
modNeg += GetTotalAuraModifier(AuraType.ModStat, aurEff =>
{
if ((aurEff.GetMiscValue() < 0 || aurEff.GetMiscValue() == (int)stat) && aurEff.GetAmount() < 0)
return true;
return false;
});
factor = GetTotalAuraMultiplier(AuraType.ModPercentStat, aurEff =>
{
if (aurEff.GetMiscValue() == -1 || aurEff.GetMiscValue() == (int)stat)
return true;
return false;
});
factor *= GetTotalAuraMultiplier(AuraType.ModTotalStatPercentage, aurEff =>
{
if (aurEff.GetMiscValue() == -1 || aurEff.GetMiscValue() == (int)stat)
return true;
return false;
});
modPos *= factor;
modNeg *= factor;
m_floatStatPosBuff[(int)stat] = modPos;
m_floatStatNegBuff[(int)stat] = modNeg;
UpdateStatBuffModForClient(stat);
}
public void ApplyStatPercentBuffMod(Stats stat, float val, bool apply)
{
MathFunctions.ApplyPercentModFloatVar(ref m_floatStatPosBuff[(int)stat], val, apply);
MathFunctions.ApplyPercentModFloatVar(ref m_floatStatNegBuff[(int)stat], val, apply);
}
void UpdateStatBuffModForClient(Stats stat)
{
SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.StatPosBuff, (int)stat), (int)m_floatStatPosBuff[(int)stat]);
@@ -204,7 +321,7 @@ namespace Game.Entities
if (school > SpellSchools.Normal)
{
UnitMods unitMod = UnitMods.ResistanceStart + (int)school;
SetResistance(school, (int)m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.BaseValue]);
SetResistance(school, (int)GetFlatModifierValue(unitMod, UnitModifierFlatType.Base));
SetBonusResistanceMod(school, (int)(GetTotalAuraModValue(unitMod) - GetResistance(school)));
}
else
@@ -216,10 +333,7 @@ namespace Game.Entities
public virtual void UpdateAttackPowerAndDamage(bool ranged = false) { }
public virtual void UpdateDamagePhysical(WeaponAttackType attType)
{
float minDamage = 0.0f;
float maxDamage = 0.0f;
CalculateMinMaxDamage(attType, false, true, out minDamage, out maxDamage);
CalculateMinMaxDamage(attType, false, true, out float minDamage, out float maxDamage);
switch (attType)
{
@@ -326,14 +440,11 @@ namespace Game.Entities
{
UnitMods unitMod = UnitMods.StatStart + (int)stat;
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));
float value = MathFunctions.CalculatePct(GetFlatModifierValue(unitMod, UnitModifierFlatType.Base), Math.Max(GetFlatModifierValue(unitMod, UnitModifierFlatType.BasePCTExcludeCreate), -100.0f));
value += GetCreateStat(stat);
value *= m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.BasePCT];
value += m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.TotalValue];
value *= m_auraModifiersGroup[(int)unitMod][(int)UnitModifierType.TotalPCT];
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
return value;
}
@@ -940,6 +1051,7 @@ namespace Game.Entities
public void ApplyModDamageDonePos(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePos, (int)school), mod, apply); }
public void ApplyModDamageDoneNeg(SpellSchools school, int mod, bool apply) { ApplyModUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDoneNeg, (int)school), mod, apply); }
public void ApplyModDamageDonePercent(SpellSchools school, float pct, bool apply) { ApplyPercentModUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePercent, (int)school), pct, apply); }
public void SetModDamageDonePercent(SpellSchools school, float pct) { SetUpdateFieldValue(ref m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModDamageDonePercent, (int)school), pct); }
public void ApplyRatingMod(CombatRating combatRating, int value, bool apply)
{
@@ -968,10 +1080,10 @@ namespace Game.Entities
float attackPowerMod = Math.Max(GetAPMultiplier(attType, normalized), 0.25f);
float baseValue = GetModifierValue(unitMod, UnitModifierType.BaseValue) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod;
float basePct = GetModifierValue(unitMod, UnitModifierType.BasePCT);
float totalValue = GetModifierValue(unitMod, UnitModifierType.TotalValue);
float totalPct = addTotalPct ? GetModifierValue(unitMod, UnitModifierType.TotalPCT) : 1.0f;
float baseValue = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + GetTotalAttackPowerValue(attType) / 3.5f * attackPowerMod;
float basePct = GetPctModifierValue(unitMod, UnitModifierPctType.Base);
float totalValue = GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
float totalPct = addTotalPct ? GetPctModifierValue(unitMod, UnitModifierPctType.Total) : 1.0f;
float weaponMinDamage = GetWeaponDamageRange(attType, WeaponDamageRange.MinDamage);
float weaponMaxDamage = GetWeaponDamageRange(attType, WeaponDamageRange.MaxDamage);
@@ -1007,9 +1119,9 @@ namespace Game.Entities
{
float value = 5.0f;
SetBaseModValue(BaseModGroup.CritPercentage, BaseModType.PCTmod, value);
SetBaseModValue(BaseModGroup.OffhandCritPercentage, BaseModType.PCTmod, value);
SetBaseModValue(BaseModGroup.RangedCritPercentage, BaseModType.PCTmod, value);
SetBaseModPctValue(BaseModGroup.CritPercentage, value);
SetBaseModPctValue(BaseModGroup.OffhandCritPercentage, value);
SetBaseModPctValue(BaseModGroup.RangedCritPercentage, value);
UpdateCritPercentage(WeaponAttackType.BaseAttack);
UpdateCritPercentage(WeaponAttackType.OffAttack);
@@ -1101,11 +1213,11 @@ namespace Game.Entities
val2 = MathFunctions.CalculatePct(minSpellPower, m_activePlayerData.OverrideAPBySpellPowerPercent);
}
SetModifierValue(unitMod, UnitModifierType.BaseValue, val2);
SetStatFlatModifier(unitMod, UnitModifierFlatType.Base, val2);
float base_attPower = GetModifierValue(unitMod, UnitModifierType.BaseValue) * GetModifierValue(unitMod, UnitModifierType.BasePCT);
float attPowerMod = GetModifierValue(unitMod, UnitModifierType.TotalValue);
float attPowerMultiplier = GetModifierValue(unitMod, UnitModifierType.TotalPCT) - 1.0f;
float base_attPower = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) * GetPctModifierValue(unitMod, UnitModifierPctType.Base);
float attPowerMod = GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
float attPowerMultiplier = GetPctModifierValue(unitMod, UnitModifierPctType.Total) - 1.0f;
if (ranged)
{
@@ -1154,10 +1266,10 @@ namespace Game.Entities
{
UnitMods unitMod = UnitMods.Armor;
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue); // base armor (from items)
float value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base); // base armor (from items)
float baseValue = value;
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT); // armor percent from items
value += GetModifierValue(unitMod, UnitModifierType.TotalValue);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base); // armor percent from items
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
//add dynamic flat mods
var mResbyIntellect = GetAuraEffectsByType(AuraType.ModResistanceOfStatPercent);
@@ -1167,7 +1279,7 @@ namespace Game.Entities
value += MathFunctions.CalculatePct(GetStat((Stats)i.GetMiscValueB()), i.GetAmount());
}
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
SetArmor((int)baseValue, (int)(value - baseValue));
@@ -1477,7 +1589,7 @@ namespace Game.Entities
public void UpdateCritPercentage(WeaponAttackType attType)
{
float applyCritLimit(float value)
static float applyCritLimit(float value)
{
if (WorldConfig.GetBoolValue(WorldCfg.StatsLimitsEnable))
value = value > WorldConfig.GetFloatValue(WorldCfg.StatsLimitsCrit) ? WorldConfig.GetFloatValue(WorldCfg.StatsLimitsCrit) : value;
@@ -1488,16 +1600,16 @@ namespace Game.Entities
{
case WeaponAttackType.OffAttack:
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.OffhandCritPercentage),
applyCritLimit(GetTotalPercentageModValue(BaseModGroup.OffhandCritPercentage) + GetRatingBonusValue(CombatRating.CritMelee)));
applyCritLimit(GetBaseModValue(BaseModGroup.OffhandCritPercentage, BaseModType.FlatMod) + GetBaseModValue(BaseModGroup.OffhandCritPercentage, BaseModType.PctMod) + GetRatingBonusValue(CombatRating.CritMelee)));
break;
case WeaponAttackType.RangedAttack:
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.RangedCritPercentage),
applyCritLimit(GetTotalPercentageModValue(BaseModGroup.RangedCritPercentage) + GetRatingBonusValue(CombatRating.CritRanged)));
applyCritLimit(GetBaseModValue(BaseModGroup.RangedCritPercentage, BaseModType.FlatMod) + GetBaseModValue(BaseModGroup.RangedCritPercentage, BaseModType.PctMod) + GetRatingBonusValue(CombatRating.CritRanged)));
break;
case WeaponAttackType.BaseAttack:
default:
SetUpdateFieldStatValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.CritPercentage),
applyCritLimit(GetTotalPercentageModValue(BaseModGroup.CritPercentage) + GetRatingBonusValue(CombatRating.CritMelee)));
applyCritLimit(GetBaseModValue(BaseModGroup.CritPercentage, BaseModType.FlatMod) + GetBaseModValue(BaseModGroup.CritPercentage, BaseModType.PctMod) + GetRatingBonusValue(CombatRating.CritMelee)));
break;
}
}
@@ -1638,10 +1750,10 @@ namespace Game.Entities
{
UnitMods unitMod = UnitMods.Health;
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue) + GetCreateHealth();
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
value += GetModifierValue(unitMod, UnitModifierType.TotalValue) + GetHealthBonusFromStamina();
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + GetCreateHealth();
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total) + GetHealthBonusFromStamina();
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
SetMaxHealth((uint)value);
}
@@ -1669,10 +1781,10 @@ namespace Game.Entities
UnitMods unitMod = UnitMods.PowerStart + (int)power;
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue) + GetCreatePowers(power);
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
value += GetModifierValue(unitMod, UnitModifierType.TotalValue);
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + GetCreatePowers(power);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
SetMaxPower(power, (int)Math.Round(value));
}
@@ -1748,8 +1860,6 @@ namespace Game.Entities
0.9720f, // Druid
0.9830f // Demon Hunter
};
void SetBaseModValue(BaseModGroup modGroup, BaseModType modType, float value) { m_auraBaseMod[(int)modGroup][(int)modType] = value; }
}
public partial class Creature
@@ -1775,7 +1885,7 @@ namespace Game.Entities
public override void UpdateArmor()
{
float baseValue = GetModifierValue(UnitMods.Armor, UnitModifierType.BaseValue);
float baseValue = GetFlatModifierValue(UnitMods.Armor, UnitModifierFlatType.Base);
float value = GetTotalAuraModValue(UnitMods.Armor);
SetArmor((int)baseValue, (int)(value - baseValue));
}
@@ -1805,10 +1915,10 @@ namespace Game.Entities
UnitMods unitMod = UnitMods.PowerStart + (int)power;
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue) + GetCreatePowers(power);
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
value += GetModifierValue(unitMod, UnitModifierType.TotalValue);
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + GetCreatePowers(power);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
SetMaxPower(power, (int)Math.Round(value));
}
@@ -1817,8 +1927,8 @@ namespace Game.Entities
{
UnitMods unitMod = ranged ? UnitMods.AttackPowerRanged : UnitMods.AttackPower;
float baseAttackPower = GetModifierValue(unitMod, UnitModifierType.BaseValue) * GetModifierValue(unitMod, UnitModifierType.BasePCT);
float attackPowerMultiplier = GetModifierValue(unitMod, UnitModifierType.TotalPCT) - 1.0f;
float baseAttackPower = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) * GetPctModifierValue(unitMod, UnitModifierPctType.Base);
float attackPowerMultiplier = GetPctModifierValue(unitMod, UnitModifierPctType.Total) - 1.0f;
if (ranged)
{
@@ -1881,10 +1991,10 @@ namespace Game.Entities
float attackPower = GetTotalAttackPowerValue(attType);
float attackSpeedMulti = Math.Max(GetAPMultiplier(attType, normalized), 0.25f);
float baseValue = GetModifierValue(unitMod, UnitModifierType.BaseValue) + (attackPower / 3.5f) * variance;
float basePct = GetModifierValue(unitMod, UnitModifierType.BasePCT) * attackSpeedMulti;
float totalValue = GetModifierValue(unitMod, UnitModifierType.TotalValue);
float totalPct = addTotalPct ? GetModifierValue(unitMod, UnitModifierType.TotalPCT) : 1.0f;
float baseValue = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + (attackPower / 3.5f) * variance;
float basePct = GetPctModifierValue(unitMod, UnitModifierPctType.Base) * attackSpeedMulti;
float totalValue = GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
float totalPct = addTotalPct ? GetPctModifierValue(unitMod, UnitModifierPctType.Total) : 1.0f;
float dmgMultiplier = GetCreatureTemplate().ModDamage; // = ModDamage * _GetDamageMod(rank);
minDamage = ((weaponMinDamage + baseValue) * dmgMultiplier * basePct + totalValue) * totalPct;
+29 -31
View File
@@ -441,7 +441,7 @@ namespace Game.Entities
SetMeleeDamageSchool((SpellSchools)cinfo.DmgSchool);
SetModifierValue(UnitMods.Armor, UnitModifierType.BaseValue, (float)petlevel * 50);
SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, (float)petlevel * 50);
SetBaseAttackTime(WeaponAttackType.BaseAttack, SharedConst.BaseAttackTime);
SetBaseAttackTime(WeaponAttackType.OffAttack, SharedConst.BaseAttackTime);
@@ -467,7 +467,7 @@ namespace Game.Entities
if (!IsHunterPet())
{
for (int i = (int)SpellSchools.Holy; i < (int)SpellSchools.Max; ++i)
SetModifierValue(UnitMods.ResistanceStart + i, UnitModifierType.BaseValue, cinfo.Resistance[i]);
SetStatFlatModifier(UnitMods.ResistanceStart + i, UnitModifierFlatType.Base, cinfo.Resistance[i]);
}
// Health, Mana or Power, Armor
@@ -478,7 +478,7 @@ namespace Game.Entities
SetCreateMana(pInfo.mana);
if (pInfo.armor > 0)
SetModifierValue(UnitMods.Armor, UnitModifierType.BaseValue, pInfo.armor);
SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, pInfo.armor);
for (byte stat = 0; stat < (int)Stats.Max; ++stat)
SetCreateStat((Stats)stat, pInfo.stats[stat]);
@@ -584,7 +584,6 @@ namespace Game.Entities
int bonus_dmg = (int)(GetOwner().SpellBaseDamageBonusDone(SpellSchoolMask.Shadow) * 0.3f);
SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel * 4 - petlevel) + bonus_dmg);
SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel * 4 + petlevel) + bonus_dmg);
break;
}
case 19833: //Snake Trap - Venomous Snake
@@ -610,8 +609,8 @@ namespace Game.Entities
SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage, (petlevel * 4 - petlevel));
SetBaseWeaponDamage(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage, (petlevel * 4 + petlevel));
SetModifierValue(UnitMods.Armor, UnitModifierType.BaseValue, GetOwner().GetArmor() * 0.35f); // Bonus Armor (35% of player armor)
SetModifierValue(UnitMods.StatStamina, UnitModifierType.BaseValue, GetOwner().GetStat(Stats.Stamina) * 0.3f); // Bonus Stamina (30% of player stamina)
SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, GetOwner().GetArmor() * 0.35f); // Bonus Armor (35% of player armor)
SetStatFlatModifier(UnitMods.StatStamina, UnitModifierFlatType.Base, GetOwner().GetStat(Stats.Stamina) * 0.3f); // Bonus Stamina (30% of player stamina)
if (!HasAura(58877))//prevent apply twice for the 2 wolves
AddAura(58877, this);//Spirit Hunt, passive, Spirit Wolves' attacks heal them and their master for 150% of damage done.
break;
@@ -673,7 +672,7 @@ namespace Game.Entities
public override bool UpdateStats(Stats stat)
{
float value = GetTotalStatValue(stat);
ApplyStatBuffMod(stat, m_statFromOwner[(int)stat], false);
UpdateStatBuffMod(stat);
float ownersBonus = 0.0f;
Unit owner = GetOwner();
@@ -712,7 +711,7 @@ namespace Game.Entities
SetStat(stat, (int)value);
m_statFromOwner[(int)stat] = ownersBonus;
ApplyStatBuffMod(stat, m_statFromOwner[(int)stat], true);
UpdateStatBuffMod(stat);
switch (stat)
{
@@ -754,7 +753,7 @@ namespace Game.Entities
{
if (school > SpellSchools.Normal)
{
float baseValue = GetModifierValue( UnitMods.ResistanceStart + (int)school, UnitModifierType.BaseValue);
float baseValue = GetFlatModifierValue(UnitMods.ResistanceStart + (int)school, UnitModifierFlatType.Base);
float bonusValue = GetTotalAuraModValue(UnitMods.ResistanceStart + (int)school) - baseValue;
// hunter and warlock pets gain 40% of owner's resistance
@@ -773,8 +772,6 @@ namespace Game.Entities
public override void UpdateArmor()
{
float baseValue = 0.0f;
float value = 0.0f;
float bonus_armor = 0.0f;
UnitMods unitMod = UnitMods.Armor;
@@ -784,11 +781,11 @@ namespace Game.Entities
else if (IsPet())
bonus_armor = GetOwner().GetArmor();
value = GetModifierValue(unitMod, UnitModifierType.BaseValue);
baseValue = value;
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
value += GetModifierValue(unitMod, UnitModifierType.TotalValue) + bonus_armor;
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base);
float baseValue = value;
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total) + bonus_armor;
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
SetArmor((int)baseValue, (int)(value - baseValue));
}
@@ -824,10 +821,10 @@ namespace Game.Entities
break;
}
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue) + GetCreateHealth();
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
value += GetModifierValue(unitMod, UnitModifierType.TotalValue) + stamina * multiplicator;
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + GetCreateHealth();
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total) + stamina * multiplicator;
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
SetMaxHealth((uint)value);
}
@@ -839,10 +836,10 @@ namespace Game.Entities
UnitMods unitMod = UnitMods.PowerStart + (int)power;
float value = GetModifierValue(unitMod, UnitModifierType.BaseValue) + GetCreatePowers(power);
value *= GetModifierValue(unitMod, UnitModifierType.BasePCT);
value += GetModifierValue(unitMod, UnitModifierType.TotalValue);
value *= GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + GetCreatePowers(power);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Base);
value += GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
value *= GetPctModifierValue(unitMod, UnitModifierPctType.Total);
SetMaxPower(power, (int)value);
}
@@ -902,11 +899,11 @@ namespace Game.Entities
}
}
SetModifierValue(UnitMods.AttackPower, UnitModifierType.BaseValue, val + bonusAP);
SetStatFlatModifier(UnitMods.AttackPower, UnitModifierFlatType.Base, val + bonusAP);
//in BASE_VALUE of UNIT_MOD_ATTACK_POWER for creatures we store data of meleeattackpower field in DB
float base_attPower = GetModifierValue(unitMod, UnitModifierType.BaseValue) * GetModifierValue(unitMod, UnitModifierType.BasePCT);
float attPowerMultiplier = GetModifierValue(unitMod, UnitModifierType.TotalPCT) - 1.0f;
float base_attPower = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) * GetPctModifierValue(unitMod, UnitModifierPctType.Base);
float attPowerMultiplier = GetPctModifierValue(unitMod, UnitModifierPctType.Total) - 1.0f;
SetAttackPower((int)base_attPower);
SetAttackPowerMultiplier(attPowerMultiplier);
@@ -944,10 +941,10 @@ namespace Game.Entities
float att_speed = GetBaseAttackTime(WeaponAttackType.BaseAttack) / 1000.0f;
float base_value = GetModifierValue(unitMod, UnitModifierType.BaseValue) + GetTotalAttackPowerValue(attType) / 3.5f * att_speed + bonusDamage;
float base_pct = GetModifierValue(unitMod, UnitModifierType.BasePCT);
float total_value = GetModifierValue(unitMod, UnitModifierType.TotalValue);
float total_pct = GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float base_value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Base) + GetTotalAttackPowerValue(attType) / 3.5f * att_speed + bonusDamage;
float base_pct = GetPctModifierValue(unitMod, UnitModifierPctType.Base);
float total_value = GetFlatModifierValue(unitMod, UnitModifierFlatType.Total);
float total_pct = GetPctModifierValue(unitMod, UnitModifierPctType.Total);
float weapon_mindamage = GetWeaponDamageRange(WeaponAttackType.BaseAttack, WeaponDamageRange.MinDamage);
float weapon_maxdamage = GetWeaponDamageRange(WeaponAttackType.BaseAttack, WeaponDamageRange.MaxDamage);
@@ -968,6 +965,7 @@ namespace Game.Entities
}
public int GetBonusDamage() { return m_bonusSpellDamage; }
public float GetBonusStatFromOwner(Stats stat) { return m_statFromOwner[(int)stat]; }
int m_bonusSpellDamage;
float[] m_statFromOwner = new float[(int)Stats.Max];
+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;
+196 -110
View File
@@ -235,8 +235,7 @@ namespace Game.Spells
if (handleMask == 0)
return;
List<AuraApplication> effectApplications = new List<AuraApplication>();
GetApplicationList(out effectApplications);
GetApplicationList(out List<AuraApplication> effectApplications);
foreach (var aurApp in effectApplications)
{
@@ -408,8 +407,7 @@ namespace Game.Spells
m_periodicTimer += m_period - (int)diff;
UpdatePeriodic(caster);
List<AuraApplication> effectApplications = new List<AuraApplication>();
GetApplicationList(out effectApplications);
GetApplicationList(out List<AuraApplication> effectApplications);
// tick on targets of effects
foreach (var appt in effectApplications)
if (appt.HasEffect(GetEffIndex()))
@@ -1658,7 +1656,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
float scale = target.GetObjectScale();
MathFunctions.ApplyPercentModFloatVar(ref scale, GetAmount(), apply);
scale += MathFunctions.CalculatePct(1.0f, apply ? GetAmount() : -GetAmount());
target.SetObjectScale(scale);
}
@@ -1783,7 +1781,7 @@ namespace Game.Spells
AuraType type = GetAuraType();
//Prevent handling aura twice
if ((apply) ? target.GetAuraEffectsByType(type).Count > 1 : target.HasAuraType(type))
if (apply ? target.GetAuraEffectsByType(type).Count > 1 : target.HasAuraType(type))
return;
Action<Unit> flagAddFn = null;
@@ -1831,11 +1829,15 @@ namespace Game.Spells
Item item = player.GetItemByPos(InventorySlots.Bag0, (byte)slot);
if (item != null)
{
WeaponAttackType attacktype = Player.GetAttackBySlot((byte)slot, item.GetTemplate().GetInventoryType());
WeaponAttackType attackType = Player.GetAttackBySlot((byte)slot, item.GetTemplate().GetInventoryType());
player.ApplyItemDependentAuras(item, !apply);
if (attacktype < WeaponAttackType.Max)
if (attackType < WeaponAttackType.Max)
{
player._ApplyWeaponDamage(slot, item, !apply);
if (!apply) // apply case already handled on item dependent aura removal (if any)
player.UpdateWeaponDependentAuras(attackType);
}
}
}
@@ -2359,7 +2361,15 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
for (byte i = 0; i < (int)SpellSchools.Max; ++i)
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
MathFunctions.ApplyPercentModFloatVar(ref target.m_threatModifier[i], GetAmount(), apply);
{
if (apply)
MathFunctions.AddPct(ref target.m_threatModifier[i], GetAmount());
else
{
float amount = target.GetTotalAuraMultiplierByMiscMask(AuraType.ModThreat, 1u << i);
target.m_threatModifier[i] = amount;
}
}
}
[AuraEffectHandler(AuraType.ModTotalThreat)]
@@ -2882,7 +2892,7 @@ namespace Game.Spells
for (byte x = (byte)SpellSchools.Normal; x < (byte)SpellSchools.Max; x++)
if (Convert.ToBoolean(GetMiscValue() & (1 << x)))
target.HandleStatModifier(UnitMods.ResistanceStart + x, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.ResistanceStart + x, UnitModifierFlatType.Total, GetAmount(), apply);
}
[AuraEffectHandler(AuraType.ModBaseResistancePct)]
@@ -2898,14 +2908,30 @@ namespace Game.Spells
{
//pets only have base armor
if (target.IsPet() && Convert.ToBoolean(GetMiscValue() & (int)SpellSchoolMask.Normal))
target.HandleStatModifier(UnitMods.Armor, UnitModifierType.BasePCT, GetAmount(), apply);
{
if (apply)
target.ApplyStatPctModifier(UnitMods.Armor, UnitModifierPctType.Base, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplierByMiscMask(AuraType.ModBaseResistancePct, (uint)SpellSchoolMask.Normal);
target.SetStatPctModifier(UnitMods.Armor, UnitModifierPctType.Base, amount);
}
}
}
else
{
for (byte x = (byte)SpellSchools.Normal; x < (byte)SpellSchools.Max; x++)
{
if (Convert.ToBoolean(GetMiscValue() & (1 << x)))
target.HandleStatModifier(UnitMods.ResistanceStart + x, UnitModifierType.BasePCT, GetAmount(), apply);
{
if (apply)
target.ApplyStatPctModifier(UnitMods.ResistanceStart + x, UnitModifierPctType.Base, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplierByMiscMask(AuraType.ModBaseResistancePct, 1u << x);
target.SetStatPctModifier(UnitMods.ResistanceStart + x, UnitModifierPctType.Base, amount);
}
}
}
}
}
@@ -2917,18 +2943,16 @@ namespace Game.Spells
return;
Unit target = aurApp.GetTarget();
int spellGroupVal = target.GetHighestExclusiveSameEffectSpellGroupValue(this, AuraType.ModResistancePct);
if (Math.Abs(spellGroupVal) >= Math.Abs(GetAmount()))
return;
for (byte i = (byte)SpellSchools.Normal; i < (byte)SpellSchools.Max; i++)
{
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
{
if (spellGroupVal != 0)
target.HandleStatModifier(UnitMods.ResistanceStart + i, UnitModifierType.TotalPCT, (float)spellGroupVal, !apply);
float amount = target.GetTotalAuraMultiplierByMiscMask(AuraType.ModResistancePct, 1u << i);
if (target.GetPctModifierValue(UnitMods.ResistanceStart + i, UnitModifierPctType.Total) == amount)
continue;
target.HandleStatModifier(UnitMods.ResistanceStart + i, UnitModifierType.TotalPCT, GetAmount(), apply);
target.SetStatPctModifier(UnitMods.ResistanceStart + i, UnitModifierPctType.Total, amount);
}
}
}
@@ -2946,13 +2970,13 @@ namespace Game.Spells
{
//only pets have base stats
if (target.IsPet() && Convert.ToBoolean(GetMiscValue() & (int)SpellSchoolMask.Normal))
target.HandleStatModifier(UnitMods.Armor, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Total, GetAmount(), apply);
}
else
{
for (byte i = (byte)SpellSchools.Normal; i < (byte)SpellSchools.Max; i++)
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
target.HandleStatModifier(UnitMods.ResistanceStart + i, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.ResistanceStart + i, UnitModifierFlatType.Total, GetAmount(), apply);
}
}
@@ -3004,14 +3028,14 @@ namespace Game.Spells
{
if (spellGroupVal != 0)
{
target.HandleStatModifier((UnitMods.StatStart + (int)i), UnitModifierType.TotalValue, (float)spellGroupVal, !apply);
target.HandleStatFlatModifier((UnitMods.StatStart + (int)i), UnitModifierFlatType.Total, (float)spellGroupVal, !apply);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
target.ApplyStatBuffMod(i, spellGroupVal, !apply);
target.UpdateStatBuffMod(i);
}
target.HandleStatModifier(UnitMods.StatStart + (int)i, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.StatStart + (int)i, UnitModifierFlatType.Total, GetAmount(), apply);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
target.ApplyStatBuffMod(i, GetAmount(), apply);
target.UpdateStatBuffMod(i);
}
}
}
@@ -3037,7 +3061,20 @@ namespace Game.Spells
for (int i = (int)Stats.Strength; i < (int)Stats.Max; ++i)
{
if (GetMiscValue() == i || GetMiscValue() == -1)
target.HandleStatModifier(UnitMods.StatStart + i, UnitModifierType.BasePCT, (float)m_amount, apply);
{
if (apply)
target.ApplyStatPctModifier(UnitMods.StatStart + i, UnitModifierPctType.Base, m_amount);
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModPercentStat, aurEff =>
{
if (aurEff.GetMiscValue() == i || aurEff.GetMiscValue() == -1)
return true;
return false;
});
target.SetStatPctModifier(UnitMods.StatStart + i, UnitModifierPctType.Base, amount);
}
}
}
}
@@ -3138,22 +3175,6 @@ namespace Game.Spells
return;
Unit target = aurApp.GetTarget();
int spellGroupVal = target.GetHighestExclusiveSameEffectSpellGroupValue(this, AuraType.ModTotalStatPercentage, true, -1);
if (Math.Abs(spellGroupVal) >= Math.Abs(GetAmount()))
return;
if (spellGroupVal != 0)
{
for (int i = (int)Stats.Strength; i < (int)Stats.Max; i++)
{
if (GetMiscValue() == i || GetMiscValue() == -1) // affect the same stats
{
target.HandleStatModifier((UnitMods.StatStart + i), UnitModifierType.TotalPCT, spellGroupVal, !apply);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
target.ApplyStatPercentBuffMod((Stats)i, spellGroupVal, !apply);
}
}
}
// save current health state
float healthPct = target.GetHealthPct();
@@ -3169,26 +3190,25 @@ namespace Game.Spells
{
if (Convert.ToBoolean(GetMiscValueB() & 1 << i) || GetMiscValueB() == 0) // 0 is also used for all stats
{
int spellGroupVal2 = target.GetHighestExclusiveSameEffectSpellGroupValue(this, AuraType.ModTotalStatPercentage, true, i);
if (Math.Abs(spellGroupVal2) >= Math.Abs(GetAmount()))
float amount = target.GetTotalAuraMultiplier(AuraType.ModTotalStatPercentage, aurEff =>
{
if ((aurEff.GetMiscValueB() & 1 << i) != 0 || aurEff.GetMiscValueB() == 0)
return true;
return false;
});
if (target.GetPctModifierValue(UnitMods.StatStart + i, UnitModifierPctType.Total) == amount)
continue;
if (spellGroupVal2 != 0)
{
target.HandleStatModifier(UnitMods.StatStart + i, UnitModifierType.TotalPCT, spellGroupVal2, !apply);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
target.ApplyStatPercentBuffMod((Stats)i, spellGroupVal2, !apply);
}
target.HandleStatModifier(UnitMods.StatStart + i, UnitModifierType.TotalPCT, GetAmount(), apply);
target.SetStatPctModifier(UnitMods.StatStart + i, UnitModifierPctType.Total, amount);
if (target.IsTypeId(TypeId.Player) || target.IsPet())
target.ApplyStatPercentBuffMod((Stats)i, GetAmount(), apply);
target.UpdateStatBuffMod((Stats)i);
}
}
// recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_UNK4 0x00000010 flag)
// recalculate current HP/MP after applying aura modifications (only for spells with SPELL_ATTR0_ABILITY 0x00000010 flag)
// this check is total bullshit i think
if (Convert.ToBoolean(GetMiscValueB() & 1 << (int)Stats.Stamina) && m_spellInfo.HasAttribute(SpellAttr0.Ability))
if ((Convert.ToBoolean(GetMiscValueB() & 1 << (int)Stats.Stamina) || GetMiscValueB() == 0) && m_spellInfo.HasAttribute(SpellAttr0.Ability))
target.SetHealth(Math.Max(MathFunctions.CalculatePct(target.GetMaxHealth(), healthPct), (zeroHealth ? 0 : 1ul)));
}
@@ -3252,8 +3272,8 @@ namespace Game.Spells
{
if (GetMiscValue() == (int)stat || GetMiscValue() == -1)
{
target.HandleStatModifier(UnitMods.StatStart + (int)stat, UnitModifierType.BasePCTExcludeCreate, m_amount, apply);
target.ApplyStatPercentBuffMod(stat, m_amount, apply);
target.HandleStatFlatModifier(UnitMods.StatStart + (int)stat, UnitModifierFlatType.BasePCTExcludeCreate, m_amount, apply);
target.UpdateStatBuffMod(stat);
}
}
}
@@ -3313,7 +3333,7 @@ namespace Game.Spells
PowerType power = (PowerType)GetMiscValue();
UnitMods unitMod = (UnitMods)(UnitMods.PowerStart + (int)power);
target.HandleStatModifier(unitMod, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(unitMod, UnitModifierFlatType.Total, GetAmount(), apply);
}
/********************************/
@@ -3385,7 +3405,7 @@ namespace Game.Spells
if (apply)
{
target.HandleStatModifier(UnitMods.Health, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Total, GetAmount(), apply);
target.ModifyHealth(GetAmount());
}
else
@@ -3396,7 +3416,7 @@ namespace Game.Spells
target.ModifyHealth(-value);
}
target.HandleStatModifier(UnitMods.Health, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Total, GetAmount(), apply);
}
}
@@ -3409,7 +3429,7 @@ namespace Game.Spells
float percent = target.GetHealthPct();
target.HandleStatModifier(UnitMods.Health, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Total, GetAmount(), apply);
// refresh percentage
if (target.GetHealth() > 0)
@@ -3429,7 +3449,7 @@ namespace Game.Spells
PowerType powerType = (PowerType)GetMiscValue();
UnitMods unitMod = (UnitMods.PowerStart + (int)powerType);
target.HandleStatModifier(unitMod, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(unitMod, UnitModifierFlatType.Total, GetAmount(), apply);
}
[AuraEffectHandler(AuraType.ModIncreaseEnergyPercent)]
@@ -3448,7 +3468,26 @@ namespace Game.Spells
int oldMaxPower = target.GetMaxPower(powerType);
// Handle aura effect for max power
target.HandleStatModifier(unitMod, UnitModifierType.TotalPCT, GetAmount(), apply);
if (apply)
target.ApplyStatPctModifier(unitMod, UnitModifierPctType.Total, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModIncreaseEnergyPercent, aurEff =>
{
if (aurEff.GetMiscValue() == (int)powerType)
return true;
return false;
});
amount *= target.GetTotalAuraMultiplier(AuraType.ModMaxPowerPct, aurEff =>
{
if (aurEff.GetMiscValue() == (int)powerType)
return true;
return false;
});
target.SetStatPctModifier(unitMod, UnitModifierPctType.Total, amount);
}
// Calculate the current power change
int change = target.GetMaxPower(powerType) - oldMaxPower;
@@ -3465,11 +3504,17 @@ namespace Game.Spells
// Unit will keep hp% after MaxHealth being modified if unit is alive.
float percent = target.GetHealthPct();
target.HandleStatModifier(UnitMods.Health, UnitModifierType.TotalPCT, GetAmount(), apply);
if (apply)
target.ApplyStatPctModifier(UnitMods.Health, UnitModifierPctType.Total, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModIncreaseHealthPercent);
target.SetStatPctModifier(UnitMods.Health, UnitModifierPctType.Total, amount);
}
if (target.GetHealth() > 0)
{
uint newHealth = (uint)Math.Max(target.CountPctFromMaxHealth((int)percent), 1);
uint newHealth = (uint)Math.Max(MathFunctions.CalculatePct(target.GetMaxHealth(), (int)percent), 1);
target.SetHealth(newHealth);
}
}
@@ -3482,7 +3527,13 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
target.HandleStatModifier(UnitMods.Health, UnitModifierType.BasePCT, GetAmount(), apply);
if (apply)
target.ApplyStatPctModifier(UnitMods.Health, UnitModifierPctType.Base, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModBaseHealthPct);
target.SetStatPctModifier(UnitMods.Health, UnitModifierPctType.Base, amount);
}
}
[AuraEffectHandler(AuraType.ModBaseManaPct)]
@@ -3491,7 +3542,15 @@ namespace Game.Spells
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat))
return;
aurApp.GetTarget().HandleStatModifier(UnitMods.Mana, UnitModifierType.BasePCT, GetAmount(), apply);
Unit target = aurApp.GetTarget();
if (apply)
target.ApplyStatPctModifier(UnitMods.Mana, UnitModifierPctType.Base, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModBaseManaPct);
target.SetStatPctModifier(UnitMods.Mana, UnitModifierPctType.Base, amount);
}
}
[AuraEffectHandler(AuraType.ModPowerDisplay)]
@@ -3550,7 +3609,26 @@ namespace Game.Spells
int oldMaxPower = target.GetMaxPower(powerType);
// Handle aura effect for max power
target.HandleStatModifier(unitMod, UnitModifierType.TotalPCT, (float)GetAmount(), apply);
if (apply)
target.ApplyStatPctModifier(unitMod, UnitModifierPctType.Total, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModMaxPowerPct, aurEff =>
{
if (aurEff.GetMiscValue() == (int)powerType)
return true;
return false;
});
amount *= target.GetTotalAuraMultiplier(AuraType.ModIncreaseEnergyPercent, aurEff =>
{
if (aurEff.GetMiscValue() == (int)powerType)
return true;
return false;
});
target.SetStatPctModifier(unitMod, UnitModifierPctType.Total, amount);
}
// Calculate the current power change
int change = target.GetMaxPower(powerType) - oldMaxPower;
@@ -3616,13 +3694,10 @@ namespace Game.Spells
return;
Player target = aurApp.GetTarget().ToPlayer();
if (!target)
return;
target.HandleBaseModValue(BaseModGroup.CritPercentage, BaseModType.FlatMod, GetAmount(), apply);
target.HandleBaseModValue(BaseModGroup.OffhandCritPercentage, BaseModType.FlatMod, GetAmount(), apply);
target.HandleBaseModValue(BaseModGroup.RangedCritPercentage, BaseModType.FlatMod, GetAmount(), apply);
target.UpdateAllWeaponDependentCritAuras();
}
[AuraEffectHandler(AuraType.ModHitChance)]
@@ -3687,9 +3762,7 @@ namespace Game.Spells
return;
}
target.ToPlayer().HandleBaseModValue(BaseModGroup.CritPercentage, BaseModType.FlatMod, GetAmount(), apply);
target.ToPlayer().HandleBaseModValue(BaseModGroup.OffhandCritPercentage, BaseModType.FlatMod, GetAmount(), apply);
target.ToPlayer().HandleBaseModValue(BaseModGroup.RangedCritPercentage, BaseModType.FlatMod, GetAmount(), apply);
target.ToPlayer().UpdateAllWeaponDependentCritAuras();
// included in Player.UpdateSpellCritChance calculation
target.ToPlayer().UpdateSpellCritChance();
@@ -3863,7 +3936,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
target.HandleStatModifier(UnitMods.AttackPower, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.AttackPower, UnitModifierFlatType.Total, GetAmount(), apply);
}
[AuraEffectHandler(AuraType.ModRangedAttackPower)]
@@ -3877,7 +3950,7 @@ namespace Game.Spells
if ((target.GetClassMask() & (uint)Class.ClassMaskWandUsers) != 0)
return;
target.HandleStatModifier(UnitMods.AttackPowerRanged, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Total, GetAmount(), apply);
}
[AuraEffectHandler(AuraType.ModAttackPowerPct)]
@@ -3889,7 +3962,13 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
//UNIT_FIELD_ATTACK_POWER_MULTIPLIER = multiplier - 1
target.HandleStatModifier(UnitMods.AttackPower, UnitModifierType.TotalPCT, GetAmount(), apply);
if (apply)
target.ApplyStatPctModifier(UnitMods.AttackPower, UnitModifierPctType.Total, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModAttackPowerPct);
target.SetStatPctModifier(UnitMods.AttackPower, UnitModifierPctType.Total, amount);
}
}
[AuraEffectHandler(AuraType.ModRangedAttackPowerPct)]
@@ -3904,7 +3983,13 @@ namespace Game.Spells
return;
//UNIT_FIELD_RANGED_ATTACK_POWER_MULTIPLIER = multiplier - 1
target.HandleStatModifier(UnitMods.AttackPowerRanged, UnitModifierType.TotalPCT, GetAmount(), apply);
if (apply)
target.ApplyStatPctModifier(UnitMods.AttackPowerRanged, UnitModifierPctType.Total, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModRangedAttackPowerPct);
target.SetStatPctModifier(UnitMods.AttackPowerRanged, UnitModifierPctType.Total, amount);
}
}
/********************************/
@@ -3919,11 +4004,7 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
if ((GetMiscValue() & (int)SpellSchoolMask.Normal) != 0)
{
target.HandleStatModifier(UnitMods.DamageMainHand, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatModifier(UnitMods.DamageOffHand, UnitModifierType.TotalValue, GetAmount(), apply);
target.HandleStatModifier(UnitMods.DamageRanged, UnitModifierType.TotalValue, GetAmount(), apply);
}
target.UpdateAllDamageDoneMods();
// Magic damage modifiers implemented in Unit::SpellBaseDamageBonusDone
// This information for client side use only
@@ -3954,35 +4035,21 @@ namespace Game.Spells
return;
Unit target = aurApp.GetTarget();
int spellGroupVal = target.GetHighestExclusiveSameEffectSpellGroupValue(this, AuraType.ModDamagePercentDone);
if (Math.Abs(spellGroupVal) >= Math.Abs(GetAmount()))
return;
// also handles spell group stacks
if (Convert.ToBoolean(GetMiscValue() & (int)SpellSchoolMask.Normal))
{
if (spellGroupVal != 0)
{
target.HandleStatModifier(UnitMods.DamageMainHand, UnitModifierType.TotalPCT, spellGroupVal, !apply);
target.HandleStatModifier(UnitMods.DamageOffHand, UnitModifierType.TotalPCT, spellGroupVal, !apply);
target.HandleStatModifier(UnitMods.DamageRanged, UnitModifierType.TotalPCT, spellGroupVal, !apply);
}
target.HandleStatModifier(UnitMods.DamageMainHand, UnitModifierType.TotalPCT, GetAmount(), apply);
target.HandleStatModifier(UnitMods.DamageOffHand, UnitModifierType.TotalPCT, GetAmount(), apply);
target.HandleStatModifier(UnitMods.DamageRanged, UnitModifierType.TotalPCT, GetAmount(), apply);
}
target.UpdateAllDamagePctDoneMods();
Player thisPlayer = target.ToPlayer();
if (thisPlayer != null)
{
for (int i = 0; i < (int)SpellSchools.Max; ++i)
for (var i = SpellSchools.Normal; i < SpellSchools.Max; ++i)
{
if (Convert.ToBoolean(GetMiscValue() & (1 << i)))
if (Convert.ToBoolean(GetMiscValue() & (1 << (int)i)))
{
if (spellGroupVal != 0)
thisPlayer.ApplyModDamageDonePercent((SpellSchools)i, spellGroupVal, !apply);
thisPlayer.ApplyModDamageDonePercent((SpellSchools)i, GetAmount(), apply);
// only aura type modifying PLAYER_FIELD_MOD_DAMAGE_DONE_PCT
float amount = thisPlayer.GetTotalAuraMultiplierByMiscMask(AuraType.ModDamagePercentDone, 1u << (int)i);
thisPlayer.SetModDamageDonePercent(i, amount);
}
}
}
@@ -3996,18 +4063,37 @@ namespace Game.Spells
Unit target = aurApp.GetTarget();
target.HandleStatModifier(UnitMods.DamageOffHand, UnitModifierType.TotalPCT, GetAmount(), apply);
// also handles spell group stacks
target.UpdateDamagePctDoneMods(WeaponAttackType.OffAttack);
}
void HandleShieldBlockValue(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
{
if (!mode.HasAnyFlag(AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat))
return;
Player player = aurApp.GetTarget().ToPlayer();
if (player != null)
player.HandleBaseModFlatValue(BaseModGroup.ShieldBlockValue, GetAmount(), apply);
}
[AuraEffectHandler(AuraType.ModShieldBlockvaluePct)]
void HandleShieldBlockValue(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
void HandleShieldBlockValuePercent(AuraApplication aurApp, AuraEffectHandleModes mode, bool apply)
{
if (!mode.HasAnyFlag((AuraEffectHandleModes.ChangeAmountMask | AuraEffectHandleModes.Stat)))
return;
Player player = aurApp.GetTarget().ToPlayer();
if (player)
player.HandleBaseModValue(BaseModGroup.ShieldBlockValue, BaseModType.PCTmod, GetAmount(), apply);
Player target = aurApp.GetTarget().ToPlayer();
if (!target)
return;
if (apply)
target.ApplyBaseModPctValue(BaseModGroup.ShieldBlockValue, GetAmount());
else
{
float amount = target.GetTotalAuraMultiplier(AuraType.ModShieldBlockvaluePct);
target.SetBaseModPctValue(BaseModGroup.ShieldBlockValue, amount);
}
}
/********************************/
@@ -4478,7 +4564,7 @@ namespace Game.Spells
}
//Adding items
uint noSpaceForCount = 0;
uint noSpaceForCount;
uint count = (uint)m_amount;
List<ItemPosCount> dest = new List<ItemPosCount>();
+10 -10
View File
@@ -1388,8 +1388,8 @@ namespace Game.Spells
Player player = m_caster.ToPlayer();
uint lockId = 0;
ObjectGuid guid = ObjectGuid.Empty;
uint lockId;
ObjectGuid guid;
// Get lockId
if (gameObjTarget != null)
@@ -1741,7 +1741,7 @@ namespace Game.Spells
for (uint count = 0; count < numSummons; ++count)
{
Position pos = new Position();
Position pos;
if (count == 0)
pos = destTarget;
else
@@ -2657,7 +2657,7 @@ namespace Game.Spells
break;
}
float weapon_total_pct = m_caster.GetModifierValue(unitMod, UnitModifierType.TotalPCT);
float weapon_total_pct = m_caster.GetPctModifierValue(unitMod, UnitModifierPctType.Total);
if (fixed_bonus != 0)
fixed_bonus = (int)(fixed_bonus * weapon_total_pct);
if (spell_bonus != 0)
@@ -2725,7 +2725,7 @@ namespace Game.Spells
if (unitTarget == null || !unitTarget.IsAlive())
return;
int addhealth = 0;
int addhealth;
// damage == 0 - heal for caster max health
if (damage == 0)
@@ -2951,7 +2951,7 @@ namespace Game.Spells
byte bag = 19;
byte slot = 0;
Item item = null;
Item item;
while (bag != 0) // 256 = 0 due to var type
{
@@ -3020,7 +3020,7 @@ namespace Game.Spells
if (unitTarget == null || !unitTarget.IsTypeId(TypeId.Unit))
return;
uint iTmpSpellId = 0;
uint iTmpSpellId;
switch (unitTarget.GetDisplayId())
{
case 25369: iTmpSpellId = 51552; break; // bloodelf female
@@ -3304,7 +3304,7 @@ namespace Game.Spells
{
if (unitTarget == null || !unitTarget.IsAlive())
return;
uint spellId1 = 0;
uint spellId1;
uint spellId2 = 0;
// Judgement self add switch
@@ -3985,7 +3985,7 @@ namespace Game.Spells
if (!m_caster.IsInWorld)
return;
uint health = 0;
uint health;
int mana = 0;
// flat case
@@ -5065,7 +5065,7 @@ namespace Game.Spells
for (uint count = 0; count < numGuardians; ++count)
{
Position pos = new Position();
Position pos;
if (count == 0)
pos = destTarget;
else