diff --git a/Source/Framework/Constants/SharedConst.cs b/Source/Framework/Constants/SharedConst.cs index b732840cb..239264f78 100644 --- a/Source/Framework/Constants/SharedConst.cs +++ b/Source/Framework/Constants/SharedConst.cs @@ -1811,6 +1811,7 @@ namespace Framework.Constants RatePowerMaelstrom, RatePowerMana, RatePowerPain, + RatePowerEssence, RatePowerRageIncome, RatePowerRageLoss, RatePowerRunicPowerIncome, diff --git a/Source/Game/Entities/Creature/Creature.cs b/Source/Game/Entities/Creature/Creature.cs index acefe4cc1..06e8c229d 100644 --- a/Source/Game/Entities/Creature/Creature.cs +++ b/Source/Game/Entities/Creature/Creature.cs @@ -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); } diff --git a/Source/Game/Entities/Creature/CreatureData.cs b/Source/Game/Entities/Creature/CreatureData.cs index 77b212dfd..977e6fef6 100644 --- a/Source/Game/Entities/Creature/CreatureData.cs +++ b/Source/Game/Entities/Creature/CreatureData.cs @@ -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 diff --git a/Source/Game/Entities/Player/Player.Combat.cs b/Source/Game/Entities/Player/Player.Combat.cs index 4ee60d871..ce83d90fb 100644 --- a/Source/Game/Entities/Player/Player.Combat.cs +++ b/Source/Game/Entities/Player/Player.Combat.cs @@ -331,7 +331,7 @@ namespace Game.Entities { base.AtExitCombat(); UpdatePotionCooldown(); - m_combatExitTime = Time.GetMSTime(); + m_regenInterruptTimestamp = GameTime.Now(); } public override float GetBlockPercent(uint attackerLevel) diff --git a/Source/Game/Entities/Player/Player.Fields.cs b/Source/Game/Entities/Player/Player.Fields.cs index 04b0b4d1e..b591ec027 100644 --- a/Source/Game/Entities/Player/Player.Fields.cs +++ b/Source/Game/Entities/Player/Player.Fields.cs @@ -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; diff --git a/Source/Game/Entities/Player/Player.cs b/Source/Game/Entities/Player/Player.cs index 0518c24df..faf24ef51 100644 --- a/Source/Game/Entities/Player/Player.cs +++ b/Source/Game/Entities/Player/Player.cs @@ -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(); diff --git a/Source/Game/Entities/StatSystem.cs b/Source/Game/Entities/StatSystem.cs index 318978c78..30ba68696 100644 --- a/Source/Game/Entities/StatSystem.cs +++ b/Source/Game/Entities/StatSystem.cs @@ -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; } diff --git a/Source/Game/Entities/TemporarySummon.cs b/Source/Game/Entities/TemporarySummon.cs index b8fe3521b..f22d494ea 100644 --- a/Source/Game/Entities/TemporarySummon.cs +++ b/Source/Game/Entities/TemporarySummon.cs @@ -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); diff --git a/Source/Game/Entities/Unit/Unit.Spells.cs b/Source/Game/Entities/Unit/Unit.Spells.cs index f3f308795..b4e0f94c9 100644 --- a/Source/Game/Entities/Unit/Unit.Spells.cs +++ b/Source/Game/Entities/Unit/Unit.Spells.cs @@ -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; diff --git a/Source/Game/Entities/Unit/Unit.cs b/Source/Game/Entities/Unit/Unit.cs index 64514026d..6a35f2f2a 100644 --- a/Source/Game/Entities/Unit/Unit.cs +++ b/Source/Game/Entities/Unit/Unit.cs @@ -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) diff --git a/Source/Game/Networking/Packets/CombatPackets.cs b/Source/Game/Networking/Packets/CombatPackets.cs index f2294f2d5..c9d375195 100644 --- a/Source/Game/Networking/Packets/CombatPackets.cs +++ b/Source/Game/Networking/Packets/CombatPackets.cs @@ -178,6 +178,21 @@ namespace Game.Networking.Packets public List 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) { } diff --git a/Source/Game/Server/WorldConfig.cs b/Source/Game/Server/WorldConfig.cs index 326d196ef..3715efdc1 100644 --- a/Source/Game/Server/WorldConfig.cs +++ b/Source/Game/Server/WorldConfig.cs @@ -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); diff --git a/Source/WorldServer/WorldServer.conf.dist b/Source/WorldServer/WorldServer.conf.dist index 8c67e9b18..ff5d375f2 100644 --- a/Source/WorldServer/WorldServer.conf.dist +++ b/Source/WorldServer/WorldServer.conf.dist @@ -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