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