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
+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