Core/Units: Power handling improvements
* Don't include creature_template power multipliers in CreateMana updatefield * Allow NPCs to have power types other than mana * Add missing Essence config regeneration rate * Fixed demon hunter powers not decaying immediately after combat * Fixed some powers decaying immediately out of combat after energizing (for example holy power) * Replace hardcoded list of powers to set to full on levelup with a db2 flag check * Updated Creature::GetPowerIndex for 10.1 new power types Port From (https://github.com/TrinityCore/TrinityCore/commit/1325e0c4b279d590acbcbb05d6abdf5fdb66a882)
This commit is contained in:
@@ -1811,6 +1811,7 @@ namespace Framework.Constants
|
||||
RatePowerMaelstrom,
|
||||
RatePowerMana,
|
||||
RatePowerPain,
|
||||
RatePowerEssence,
|
||||
RatePowerRageIncome,
|
||||
RatePowerRageLoss,
|
||||
RatePowerRunicPowerIncome,
|
||||
|
||||
@@ -1465,23 +1465,23 @@ namespace Game.Entities
|
||||
SetHealth(health);
|
||||
ResetPlayerDamageReq();
|
||||
|
||||
// mana
|
||||
uint mana = stats.GenerateMana(cInfo);
|
||||
SetCreateMana(mana);
|
||||
|
||||
switch (GetClass())
|
||||
{
|
||||
case Class.Paladin:
|
||||
case Class.Mage:
|
||||
SetMaxPower(PowerType.Mana, (int)mana);
|
||||
SetPower(PowerType.Mana, (int)mana);
|
||||
break;
|
||||
default: // We don't set max power here, 0 makes power bar hidden
|
||||
break;
|
||||
}
|
||||
|
||||
SetStatFlatModifier(UnitMods.Health, UnitModifierFlatType.Base, health);
|
||||
|
||||
// mana
|
||||
PowerType powerType = CalculateDisplayPowerType();
|
||||
SetCreateMana(stats.BaseMana);
|
||||
SetStatPctModifier(UnitMods.PowerStart + (int)powerType, UnitModifierPctType.Base, cInfo.ModMana * cInfo.ModManaExtra);
|
||||
SetPowerType(powerType);
|
||||
|
||||
PowerTypeRecord powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(powerType);
|
||||
if (powerTypeEntry != null)
|
||||
{
|
||||
if (powerTypeEntry.GetFlags().HasFlag(PowerTypeFlags.UnitsUseDefaultPowerOnInit))
|
||||
SetPower(powerType, powerTypeEntry.DefaultPower);
|
||||
else
|
||||
SetFullPower(powerType);
|
||||
}
|
||||
|
||||
//Damage
|
||||
float basedamage = GetBaseDamageForLevel(level);
|
||||
float weaponBaseMinDamage = basedamage;
|
||||
@@ -1499,7 +1499,7 @@ namespace Game.Entities
|
||||
SetStatFlatModifier(UnitMods.AttackPower, UnitModifierFlatType.Base, stats.AttackPower);
|
||||
SetStatFlatModifier(UnitMods.AttackPowerRanged, UnitModifierFlatType.Base, stats.RangedAttackPower);
|
||||
|
||||
float armor = GetBaseArmorForLevel(level); /// @todo Why is this treated as uint32 when it's a float?
|
||||
float armor = GetBaseArmorForLevel(level);
|
||||
SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, armor);
|
||||
}
|
||||
|
||||
|
||||
@@ -271,16 +271,6 @@ namespace Game.Entities
|
||||
public uint BaseMana;
|
||||
public uint AttackPower;
|
||||
public uint RangedAttackPower;
|
||||
|
||||
// Helpers
|
||||
public uint GenerateMana(CreatureTemplate info)
|
||||
{
|
||||
// Mana can be 0.
|
||||
if (BaseMana == 0)
|
||||
return 0;
|
||||
|
||||
return (uint)Math.Ceiling(BaseMana * info.ModMana * info.ModManaExtra);
|
||||
}
|
||||
}
|
||||
|
||||
public class CreatureLocale
|
||||
|
||||
@@ -331,7 +331,7 @@ namespace Game.Entities
|
||||
{
|
||||
base.AtExitCombat();
|
||||
UpdatePotionCooldown();
|
||||
m_combatExitTime = Time.GetMSTime();
|
||||
m_regenInterruptTimestamp = GameTime.Now();
|
||||
}
|
||||
|
||||
public override float GetBlockPercent(uint attackerLevel)
|
||||
|
||||
@@ -14,6 +14,7 @@ using Game.Maps;
|
||||
using Game.Misc;
|
||||
using Game.Networking.Packets;
|
||||
using Game.Spells;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
|
||||
@@ -142,7 +143,7 @@ namespace Game.Entities
|
||||
uint m_deathTimer;
|
||||
long m_deathExpireTime;
|
||||
byte m_swingErrorMsg;
|
||||
uint m_combatExitTime;
|
||||
DateTime m_regenInterruptTimestamp;
|
||||
uint m_regenTimerCount;
|
||||
uint m_foodEmoteTimerCount;
|
||||
uint m_weaponChangeTimer;
|
||||
|
||||
@@ -46,6 +46,8 @@ namespace Game.Entities
|
||||
if (!GetSession().HasPermission(RBACPermissions.CanFilterWhispers))
|
||||
SetAcceptWhispers(true);
|
||||
|
||||
m_regenInterruptTimestamp = GameTime.Now();
|
||||
|
||||
m_zoneUpdateId = 0xffffffff;
|
||||
m_nextSave = WorldConfig.GetUIntValue(WorldCfg.IntervalSave);
|
||||
m_customizationsChanged = false;
|
||||
@@ -3342,7 +3344,7 @@ namespace Game.Entities
|
||||
|
||||
if (!IsInCombat())
|
||||
{
|
||||
if (powerType.RegenInterruptTimeMS != 0 && Time.GetMSTimeDiffToNow(m_combatExitTime) < powerType.RegenInterruptTimeMS)
|
||||
if (powerType.GetFlags().HasFlag(PowerTypeFlags.UseRegenInterrupt) && m_regenInterruptTimestamp + TimeSpan.FromMicroseconds(powerType.RegenInterruptTimeMS) < GameTime.Now())
|
||||
return;
|
||||
|
||||
addvalue = (powerType.RegenPeace + m_unitData.PowerRegenFlatModifier[(int)powerIndex]) * 0.001f * RegenTimer;
|
||||
@@ -3371,13 +3373,13 @@ namespace Game.Entities
|
||||
WorldCfg.RatePowerArcaneCharges,
|
||||
WorldCfg.RatePowerFury,
|
||||
WorldCfg.RatePowerPain,
|
||||
0, // todo add config for Essence power
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0,
|
||||
0
|
||||
WorldCfg.RatePowerEssence,
|
||||
0, // runes
|
||||
0, // runes
|
||||
0, // runes
|
||||
0, // alternate
|
||||
0, // alternate
|
||||
0, // alternate
|
||||
};
|
||||
|
||||
if (RatesForPower[(int)power] != 0)
|
||||
@@ -3470,6 +3472,18 @@ namespace Game.Entities
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public void InterruptPowerRegen(PowerType power)
|
||||
{
|
||||
uint powerIndex = GetPowerIndex(power);
|
||||
if (powerIndex == (uint)PowerType.Max || powerIndex >= (uint)PowerType.MaxPerClass)
|
||||
return;
|
||||
|
||||
m_regenInterruptTimestamp = GameTime.Now();
|
||||
m_powerFraction[powerIndex] = 0.0f;
|
||||
SendPacket(new InterruptPowerRegen(power));
|
||||
}
|
||||
|
||||
void RegenerateHealth()
|
||||
{
|
||||
uint curValue = (uint)GetHealth();
|
||||
@@ -5046,7 +5060,9 @@ namespace Game.Entities
|
||||
|
||||
// Only health and mana are set to maximum.
|
||||
SetFullHealth();
|
||||
SetFullPower(PowerType.Mana);
|
||||
foreach (PowerTypeRecord powerType in CliDB.PowerTypeStorage.Values)
|
||||
if (powerType.GetFlags().HasFlag(PowerTypeFlags.SetToMaxOnLevelUp))
|
||||
SetFullPower(powerType.PowerTypeEnum);
|
||||
|
||||
// update level to hunter/summon pet
|
||||
Pet pet = GetPet();
|
||||
|
||||
@@ -311,7 +311,9 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
public virtual bool UpdateStats(Stats stat) { return false; }
|
||||
|
||||
public virtual bool UpdateAllStats() { return false; }
|
||||
|
||||
public virtual void UpdateResistances(SpellSchools school)
|
||||
{
|
||||
if (school > SpellSchools.Normal)
|
||||
@@ -331,10 +333,15 @@ namespace Game.Entities
|
||||
else
|
||||
UpdateArmor();
|
||||
}
|
||||
|
||||
public virtual void UpdateArmor() { }
|
||||
|
||||
public virtual void UpdateMaxHealth() { }
|
||||
|
||||
public virtual void UpdateMaxPower(PowerType power) { }
|
||||
|
||||
public virtual void UpdateAttackPowerAndDamage(bool ranged = false) { }
|
||||
|
||||
public virtual void UpdateDamagePhysical(WeaponAttackType attType)
|
||||
{
|
||||
CalculateMinMaxDamage(attType, false, true, out float minDamage, out float maxDamage);
|
||||
@@ -356,6 +363,7 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public virtual void CalculateMinMaxDamage(WeaponAttackType attType, bool normalized, bool addTotalPct, out float minDamage, out float maxDamage)
|
||||
{
|
||||
minDamage = 0f;
|
||||
@@ -370,36 +378,48 @@ namespace Game.Entities
|
||||
|
||||
//Stats
|
||||
public float GetStat(Stats stat) { return m_unitData.Stats[(int)stat]; }
|
||||
|
||||
public void SetStat(Stats stat, int val) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Stats, (int)stat), val); }
|
||||
|
||||
public uint GetCreateMana() { return m_unitData.BaseMana; }
|
||||
|
||||
public void SetCreateMana(uint val) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BaseMana), val); }
|
||||
|
||||
public uint GetArmor()
|
||||
{
|
||||
return (uint)GetResistance(SpellSchools.Normal);
|
||||
}
|
||||
|
||||
public void SetArmor(int val, int bonusVal)
|
||||
{
|
||||
SetResistance(SpellSchools.Normal, val);
|
||||
SetBonusResistanceMod(SpellSchools.Normal, bonusVal);
|
||||
}
|
||||
|
||||
public float GetCreateStat(Stats stat)
|
||||
{
|
||||
return CreateStats[(int)stat];
|
||||
}
|
||||
|
||||
public void SetCreateStat(Stats stat, float val)
|
||||
{
|
||||
CreateStats[(int)stat] = val;
|
||||
}
|
||||
|
||||
public float GetPosStat(Stats stat) { return m_unitData.StatPosBuff[(int)stat]; }
|
||||
|
||||
public float GetNegStat(Stats stat) { return m_unitData.StatNegBuff[(int)stat]; }
|
||||
|
||||
public int GetResistance(SpellSchools school)
|
||||
{
|
||||
return m_unitData.Resistances[(int)school];
|
||||
}
|
||||
|
||||
public int GetBonusResistanceMod(SpellSchools school)
|
||||
{
|
||||
return m_unitData.BonusResistanceMods[(int)school];
|
||||
}
|
||||
|
||||
public int GetResistance(SpellSchoolMask mask)
|
||||
{
|
||||
int? resist = null;
|
||||
@@ -413,13 +433,21 @@ namespace Game.Entities
|
||||
// resist value will never be negative here
|
||||
return resist.HasValue ? resist.Value : 0;
|
||||
}
|
||||
|
||||
public void SetResistance(SpellSchools school, int val) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.Resistances, (int)school), val); }
|
||||
|
||||
public void SetBonusResistanceMod(SpellSchools school, int val) { SetUpdateFieldValue(ref m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BonusResistanceMods, (int)school), val); }
|
||||
|
||||
public void SetModCastingSpeed(float castingSpeed) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModCastingSpeed), castingSpeed); }
|
||||
|
||||
public void SetModSpellHaste(float spellHaste) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModSpellHaste), spellHaste); }
|
||||
|
||||
public void SetModHaste(float haste) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHaste), haste); }
|
||||
|
||||
public void SetModRangedHaste(float rangedHaste) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModRangedHaste), rangedHaste); }
|
||||
|
||||
public void SetModHasteRegen(float hasteRegen) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModHasteRegen), hasteRegen); }
|
||||
|
||||
public void SetModTimeRate(float timeRate) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.ModTimeRate), timeRate); }
|
||||
|
||||
public void InitStatBuffMods()
|
||||
@@ -436,10 +464,12 @@ namespace Game.Entities
|
||||
{
|
||||
return canModifyStats;
|
||||
}
|
||||
|
||||
public void SetCanModifyStats(bool modifyStats)
|
||||
{
|
||||
canModifyStats = modifyStats;
|
||||
}
|
||||
|
||||
public float GetTotalStatValue(Stats stat)
|
||||
{
|
||||
UnitMods unitMod = UnitMods.StatStart + (int)stat;
|
||||
@@ -455,8 +485,11 @@ namespace Game.Entities
|
||||
|
||||
//Health
|
||||
public uint GetCreateHealth() { return m_unitData.BaseHealth; }
|
||||
|
||||
public void SetCreateHealth(uint val) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.BaseHealth), val); }
|
||||
|
||||
public ulong GetHealth() { return m_unitData.Health; }
|
||||
|
||||
public void SetHealth(ulong val)
|
||||
{
|
||||
if (GetDeathState() == DeathState.JustDied || GetDeathState() == DeathState.Corpse)
|
||||
@@ -489,7 +522,9 @@ namespace Game.Entities
|
||||
pet.SetGroupUpdateFlag(GroupUpdatePetFlags.CurHp);
|
||||
}
|
||||
}
|
||||
|
||||
public ulong GetMaxHealth() { return m_unitData.MaxHealth; }
|
||||
|
||||
public void SetMaxHealth(ulong val)
|
||||
{
|
||||
if (val == 0)
|
||||
@@ -514,23 +549,34 @@ namespace Game.Entities
|
||||
if (val < health)
|
||||
SetHealth(val);
|
||||
}
|
||||
|
||||
public float GetHealthPct() { return GetMaxHealth() != 0 ? 100.0f * GetHealth() / GetMaxHealth() : 0.0f; }
|
||||
|
||||
public void SetFullHealth() { SetHealth(GetMaxHealth()); }
|
||||
|
||||
public bool IsFullHealth() { return GetHealth() == GetMaxHealth(); }
|
||||
|
||||
public bool HealthBelowPct(int pct) { return GetHealth() < CountPctFromMaxHealth(pct); }
|
||||
|
||||
public bool HealthBelowPctDamaged(int pct, uint damage) { return GetHealth() - damage < CountPctFromMaxHealth(pct); }
|
||||
|
||||
public bool HealthAbovePct(int pct) { return GetHealth() > CountPctFromMaxHealth(pct); }
|
||||
|
||||
public bool HealthAbovePctHealed(int pct, uint heal) { return GetHealth() + heal > CountPctFromMaxHealth(pct); }
|
||||
|
||||
public ulong CountPctFromMaxHealth(int pct) { return MathFunctions.CalculatePct(GetMaxHealth(), pct); }
|
||||
|
||||
public ulong CountPctFromCurHealth(int pct) { return MathFunctions.CalculatePct(GetHealth(), pct); }
|
||||
|
||||
public virtual float GetHealthMultiplierForTarget(WorldObject target) { return 1.0f; }
|
||||
|
||||
public virtual float GetDamageMultiplierForTarget(WorldObject target) { return 1.0f; }
|
||||
|
||||
public virtual float GetArmorMultiplierForTarget(WorldObject target) { return 1.0f; }
|
||||
|
||||
//Powers
|
||||
public PowerType GetPowerType() { return (PowerType)(byte)m_unitData.DisplayPower; }
|
||||
|
||||
public void SetPowerType(PowerType powerType, bool sendUpdate = true)
|
||||
{
|
||||
if (GetPowerType() == powerType)
|
||||
@@ -573,6 +619,7 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void SetOverrideDisplayPowerId(uint powerDisplayId) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.OverrideDisplayPowerID), powerDisplayId); }
|
||||
|
||||
public void SetMaxPower(PowerType powerType, int val)
|
||||
@@ -600,6 +647,7 @@ namespace Game.Entities
|
||||
if (val < cur_power)
|
||||
SetPower(powerType, val);
|
||||
}
|
||||
|
||||
public void SetPower(PowerType powerType, int val, bool withPowerUpdate = true)
|
||||
{
|
||||
uint powerIndex = GetPowerIndex(powerType);
|
||||
@@ -637,7 +685,9 @@ namespace Game.Entities
|
||||
pet.SetGroupUpdateFlag(GROUP_UPDATE_FLAG_PET_CUR_POWER);
|
||||
}*/
|
||||
}
|
||||
|
||||
public void SetFullPower(PowerType powerType) { SetPower(powerType, GetMaxPower(powerType)); }
|
||||
|
||||
public int GetPower(PowerType powerType)
|
||||
{
|
||||
uint powerIndex = GetPowerIndex(powerType);
|
||||
@@ -646,6 +696,7 @@ namespace Game.Entities
|
||||
|
||||
return m_unitData.Power[(int)powerIndex];
|
||||
}
|
||||
|
||||
public int GetMaxPower(PowerType powerType)
|
||||
{
|
||||
uint powerIndex = GetPowerIndex(powerType);
|
||||
@@ -654,7 +705,8 @@ namespace Game.Entities
|
||||
|
||||
return (int)(uint)m_unitData.MaxPower[(int)powerIndex];
|
||||
}
|
||||
public int GetCreatePowerValue(PowerType powerType)
|
||||
|
||||
public virtual int GetCreatePowerValue(PowerType powerType)
|
||||
{
|
||||
if (powerType == PowerType.Mana)
|
||||
return (int)GetCreateMana();
|
||||
@@ -665,7 +717,9 @@ namespace Game.Entities
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
public virtual uint GetPowerIndex(PowerType powerType) { return 0; }
|
||||
|
||||
public float GetPowerPct(PowerType powerType) { return GetMaxPower(powerType) != 0 ? 100.0f * GetPower(powerType) / GetMaxPower(powerType) : 0.0f; }
|
||||
|
||||
void TriggerOnPowerChangeAuras(PowerType power, int oldVal, int newVal)
|
||||
@@ -773,15 +827,25 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
public void SetAttackPower(int attackPower) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPower), attackPower); }
|
||||
|
||||
public void SetAttackPowerModPos(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPowerModPos), attackPowerMod); }
|
||||
|
||||
public void SetAttackPowerModNeg(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPowerModNeg), attackPowerMod); }
|
||||
|
||||
public void SetAttackPowerMultiplier(float attackPowerMult) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.AttackPowerMultiplier), attackPowerMult); }
|
||||
|
||||
public void SetRangedAttackPower(int attackPower) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPower), attackPower); }
|
||||
|
||||
public void SetRangedAttackPowerModPos(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPowerModPos), attackPowerMod); }
|
||||
|
||||
public void SetRangedAttackPowerModNeg(int attackPowerMod) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPowerModNeg), attackPowerMod); }
|
||||
|
||||
public void SetRangedAttackPowerMultiplier(float attackPowerMult) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedAttackPowerMultiplier), attackPowerMult); }
|
||||
|
||||
public void SetMainHandWeaponAttackPower(int attackPower) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.MainHandWeaponAttackPower), attackPower); }
|
||||
|
||||
public void SetOffHandWeaponAttackPower(int attackPower) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.OffHandWeaponAttackPower), attackPower); }
|
||||
|
||||
public void SetRangedWeaponAttackPower(int attackPower) { SetUpdateFieldValue(m_values.ModifyValue(m_unitData).ModifyValue(m_unitData.RangedWeaponAttackPower), attackPower); }
|
||||
|
||||
//Chances
|
||||
@@ -917,6 +981,7 @@ namespace Game.Entities
|
||||
chance -= GetTotalAuraModifier(AuraType.ModExpertise) / 4.0f;
|
||||
return Math.Max(chance, 0.0f);
|
||||
}
|
||||
|
||||
float GetUnitParryChance(WeaponAttackType attType, Unit victim)
|
||||
{
|
||||
int levelDiff = (int)(victim.GetLevelForTarget(this) - GetLevelForTarget(victim));
|
||||
@@ -957,12 +1022,14 @@ namespace Game.Entities
|
||||
chance -= GetTotalAuraModifier(AuraType.ModExpertise) / 4.0f;
|
||||
return Math.Max(chance, 0.0f);
|
||||
}
|
||||
|
||||
float GetUnitMissChance()
|
||||
{
|
||||
float miss_chance = 5.0f;
|
||||
|
||||
return miss_chance;
|
||||
}
|
||||
|
||||
float GetUnitBlockChance(WeaponAttackType attType, Unit victim)
|
||||
{
|
||||
int levelDiff = (int)(victim.GetLevelForTarget(this) - GetLevelForTarget(victim));
|
||||
@@ -1116,13 +1183,17 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
public void ApplyModTargetResistance(int mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModTargetResistance), mod, apply); }
|
||||
|
||||
public void ApplyModTargetPhysicalResistance(int mod, bool apply) { ApplyModUpdateFieldValue(m_values.ModifyValue(m_activePlayerData).ModifyValue(m_activePlayerData.ModTargetPhysicalResistance), mod, apply); }
|
||||
|
||||
public void RecalculateRating(CombatRating cr) { ApplyRatingMod(cr, 0, true); }
|
||||
|
||||
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)
|
||||
@@ -1249,6 +1320,7 @@ namespace Game.Entities
|
||||
UpdateAttackPowerAndDamage(true);
|
||||
}
|
||||
}
|
||||
|
||||
public uint GetBaseSpellPowerBonus() { return m_baseSpellPower; }
|
||||
|
||||
public override void UpdateAttackPowerAndDamage(bool ranged = false)
|
||||
@@ -1376,6 +1448,7 @@ namespace Game.Entities
|
||||
|
||||
UpdateAllStats();
|
||||
}
|
||||
|
||||
void _RemoveAllStatBonuses()
|
||||
{
|
||||
SetCanModifyStats(false);
|
||||
@@ -1394,6 +1467,7 @@ namespace Game.Entities
|
||||
for (CombatRating cr = 0; cr < CombatRating.Max; ++cr)
|
||||
UpdateRating(cr);
|
||||
}
|
||||
|
||||
public void UpdateRating(CombatRating cr)
|
||||
{
|
||||
int amount = baseRatingValue[(int)cr];
|
||||
@@ -1519,6 +1593,7 @@ namespace Game.Entities
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateMastery()
|
||||
{
|
||||
if (!CanUseMastery())
|
||||
@@ -1932,6 +2007,7 @@ namespace Game.Entities
|
||||
|
||||
SetMaxHealth((uint)value);
|
||||
}
|
||||
|
||||
float GetHealthBonusFromStamina()
|
||||
{
|
||||
// Taken from PaperDollFrame.lua - 6.0.3.19085
|
||||
@@ -1944,10 +2020,12 @@ namespace Game.Entities
|
||||
|
||||
return stamina * ratio;
|
||||
}
|
||||
|
||||
public override uint GetPowerIndex(PowerType powerType)
|
||||
{
|
||||
return Global.DB2Mgr.GetPowerIndexByClass(powerType, GetClass());
|
||||
}
|
||||
|
||||
public override void UpdateMaxPower(PowerType power)
|
||||
{
|
||||
uint powerIndex = GetPowerIndex(power);
|
||||
@@ -2023,6 +2101,16 @@ namespace Game.Entities
|
||||
|
||||
public partial class Creature
|
||||
{
|
||||
public override int GetCreatePowerValue(PowerType power)
|
||||
{
|
||||
var powerType = Global.DB2Mgr.GetPowerTypeEntry(power);
|
||||
if (powerType != null)
|
||||
if (!powerType.GetFlags().HasFlag(PowerTypeFlags.IsUsedByNPCs))
|
||||
return 0;
|
||||
|
||||
return base.GetCreatePowerValue(power);
|
||||
}
|
||||
|
||||
public override bool UpdateStats(Stats stat)
|
||||
{
|
||||
return true;
|
||||
@@ -2059,10 +2147,22 @@ namespace Game.Entities
|
||||
{
|
||||
if (powerType == GetPowerType())
|
||||
return 0;
|
||||
if (powerType == PowerType.AlternatePower)
|
||||
return 1;
|
||||
if (powerType == PowerType.ComboPoints)
|
||||
return 2;
|
||||
|
||||
switch (powerType)
|
||||
{
|
||||
case PowerType.ComboPoints:
|
||||
return 2;
|
||||
case PowerType.AlternatePower:
|
||||
return 1;
|
||||
case PowerType.AlternateQuest:
|
||||
return 3;
|
||||
case PowerType.AlternateEncounter:
|
||||
return 4;
|
||||
case PowerType.AlternateMount:
|
||||
return 5;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return (uint)PowerType.Max;
|
||||
}
|
||||
|
||||
@@ -563,6 +563,8 @@ namespace Game.Entities
|
||||
SetStatFlatModifier(UnitMods.ResistanceStart + i, UnitModifierFlatType.Base, cinfo.Resistance[i]);
|
||||
}
|
||||
|
||||
PowerType powerType = CalculateDisplayPowerType();
|
||||
|
||||
// Health, Mana or Power, Armor
|
||||
PetLevelInfo pInfo = Global.ObjectMgr.GetPetLevelInfo(creature_ID, petlevel);
|
||||
if (pInfo != null) // exist in DB
|
||||
@@ -570,6 +572,8 @@ namespace Game.Entities
|
||||
SetCreateHealth(pInfo.health);
|
||||
SetCreateMana(pInfo.mana);
|
||||
|
||||
SetStatPctModifier(UnitMods.PowerStart + (int)powerType, UnitModifierPctType.Base, 1.0f);
|
||||
|
||||
if (pInfo.armor > 0)
|
||||
SetStatFlatModifier(UnitMods.Armor, UnitModifierFlatType.Base, pInfo.armor);
|
||||
|
||||
@@ -583,7 +587,7 @@ namespace Game.Entities
|
||||
ApplyLevelScaling();
|
||||
|
||||
SetCreateHealth((uint)(Global.DB2Mgr.EvaluateExpectedStat(ExpectedStatType.CreatureHealth, petlevel, cinfo.GetHealthScalingExpansion(), m_unitData.ContentTuningID, (Class)cinfo.UnitClass) * cinfo.ModHealth * cinfo.ModHealthExtra * GetHealthMod(cinfo.Rank)));
|
||||
SetCreateMana(stats.GenerateMana(cinfo));
|
||||
SetCreateMana(stats.BaseMana);
|
||||
|
||||
SetCreateStat(Stats.Strength, 22);
|
||||
SetCreateStat(Stats.Agility, 22);
|
||||
@@ -592,17 +596,7 @@ namespace Game.Entities
|
||||
}
|
||||
|
||||
// Power
|
||||
if (petType == PetType.Hunter) // Hunter pets have focus
|
||||
SetPowerType(PowerType.Focus);
|
||||
else if (IsPetGhoul() || IsPetAbomination()) // DK pets have energy
|
||||
{
|
||||
SetPowerType(PowerType.Energy);
|
||||
SetFullPower(PowerType.Energy);
|
||||
}
|
||||
else if (IsWarlockPet()) // Warlock pets have energy (since 5.x)
|
||||
SetPowerType(PowerType.Energy);
|
||||
else
|
||||
SetPowerType(PowerType.Mana);
|
||||
SetPowerType(powerType);
|
||||
|
||||
// Damage
|
||||
SetBonusDamage(0);
|
||||
|
||||
@@ -1172,6 +1172,15 @@ namespace Game.Entities
|
||||
|
||||
public void EnergizeBySpell(Unit victim, SpellInfo spellInfo, int damage, PowerType powerType)
|
||||
{
|
||||
Player player = victim.ToPlayer();
|
||||
if (player != null)
|
||||
{
|
||||
var powerTypeEntry = Global.DB2Mgr.GetPowerTypeEntry(powerType);
|
||||
if (powerTypeEntry != null)
|
||||
if (powerTypeEntry.GetFlags().HasFlag(PowerTypeFlags.UseRegenInterrupt))
|
||||
player.InterruptPowerRegen(powerType);
|
||||
}
|
||||
|
||||
int gain = victim.ModifyPower(powerType, damage, false);
|
||||
int overEnergize = damage - gain;
|
||||
|
||||
|
||||
@@ -1662,7 +1662,7 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
public void UpdateDisplayPower()
|
||||
public PowerType CalculateDisplayPowerType()
|
||||
{
|
||||
PowerType displayPower = PowerType.Mana;
|
||||
switch (GetShapeshiftForm())
|
||||
@@ -1686,22 +1686,18 @@ namespace Game.Entities
|
||||
AuraEffect powerTypeAura = powerTypeAuras.First();
|
||||
displayPower = (PowerType)powerTypeAura.GetMiscValue();
|
||||
}
|
||||
else if (GetTypeId() == TypeId.Player)
|
||||
else
|
||||
{
|
||||
ChrClassesRecord cEntry = CliDB.ChrClassesStorage.LookupByKey(GetClass());
|
||||
if (cEntry != null && cEntry.DisplayPower < PowerType.Max)
|
||||
displayPower = cEntry.DisplayPower;
|
||||
}
|
||||
else if (GetTypeId() == TypeId.Unit)
|
||||
{
|
||||
|
||||
Vehicle vehicle = GetVehicleKit();
|
||||
if (vehicle)
|
||||
{
|
||||
PowerDisplayRecord powerDisplay = CliDB.PowerDisplayStorage.LookupByKey(vehicle.GetVehicleInfo().PowerDisplayID[0]);
|
||||
if (powerDisplay != null)
|
||||
displayPower = (PowerType)powerDisplay.ActualType;
|
||||
else if (GetClass() == Class.Rogue)
|
||||
displayPower = PowerType.Energy;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -1719,7 +1715,12 @@ namespace Game.Entities
|
||||
}
|
||||
}
|
||||
|
||||
SetPowerType(displayPower);
|
||||
return displayPower;
|
||||
}
|
||||
|
||||
public void UpdateDisplayPower()
|
||||
{
|
||||
SetPowerType(CalculateDisplayPowerType());
|
||||
}
|
||||
|
||||
public void SetSheath(SheathState sheathed)
|
||||
|
||||
@@ -178,6 +178,21 @@ namespace Game.Networking.Packets
|
||||
public List<PowerUpdatePower> Powers;
|
||||
}
|
||||
|
||||
class InterruptPowerRegen : ServerPacket
|
||||
{
|
||||
public int PowerType;
|
||||
|
||||
public InterruptPowerRegen(PowerType powerType) : base(ServerOpcodes.InterruptPowerRegen, ConnectionType.Instance)
|
||||
{
|
||||
PowerType = (int)powerType;
|
||||
}
|
||||
|
||||
public override void Write()
|
||||
{
|
||||
_worldPacket.WriteInt32(PowerType);
|
||||
}
|
||||
}
|
||||
|
||||
public class SetSheathed : ClientPacket
|
||||
{
|
||||
public SetSheathed(WorldPacket packet) : base(packet) { }
|
||||
|
||||
@@ -54,6 +54,7 @@ namespace Game
|
||||
SetRegenRate(WorldCfg.RatePowerArcaneCharges, "Rate.ArcaneCharges.Loss");
|
||||
SetRegenRate(WorldCfg.RatePowerFury, "Rate.Fury.Loss");
|
||||
SetRegenRate(WorldCfg.RatePowerPain, "Rate.Pain.Loss");
|
||||
SetRegenRate(WorldCfg.RatePowerEssence, "Rate.Essence.Loss");
|
||||
|
||||
Values[WorldCfg.RateSkillDiscovery] = GetDefaultValue("Rate.Skill.Discovery", 1.0f);
|
||||
Values[WorldCfg.RateDropItemPoor] = GetDefaultValue("Rate.Drop.Item.Poor", 1.0f);
|
||||
|
||||
@@ -2276,6 +2276,7 @@ Rate.Insanity.Loss = 1
|
||||
Rate.ArcaneCharges.Loss= 1
|
||||
Rate.Fury.Loss = 1
|
||||
Rate.Pain.Loss = 1
|
||||
Rate.Essence.Loss = 1
|
||||
|
||||
#
|
||||
# Rate.Skill.Discovery
|
||||
|
||||
Reference in New Issue
Block a user