aboutsummaryrefslogtreecommitdiff
path: root/src/server/game
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2023-05-09 23:16:30 +0200
committerShauren <shauren.trinity@gmail.com>2023-05-09 23:16:30 +0200
commit1325e0c4b279d590acbcbb05d6abdf5fdb66a882 (patch)
treee0c7e9db6f656fabce61eeba3b280c55e69436b5 /src/server/game
parent8828af2a5e3754e45893e0d62efae86747dfa4f2 (diff)
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
Diffstat (limited to 'src/server/game')
-rw-r--r--src/server/game/DataStores/DB2Stores.h1
-rw-r--r--src/server/game/DataStores/DBCEnums.h16
-rw-r--r--src/server/game/Entities/Creature/Creature.cpp25
-rw-r--r--src/server/game/Entities/Creature/Creature.h1
-rw-r--r--src/server/game/Entities/Creature/CreatureData.h9
-rw-r--r--src/server/game/Entities/Pet/Pet.cpp18
-rw-r--r--src/server/game/Entities/Player/Player.cpp28
-rw-r--r--src/server/game/Entities/Player/Player.h3
-rw-r--r--src/server/game/Entities/Unit/StatSystem.cpp39
-rw-r--r--src/server/game/Entities/Unit/Unit.cpp35
-rw-r--r--src/server/game/Entities/Unit/Unit.h3
-rw-r--r--src/server/game/Server/Packets/CombatPackets.cpp7
-rw-r--r--src/server/game/Server/Packets/CombatPackets.h11
-rw-r--r--src/server/game/Server/Protocol/Opcodes.cpp2
-rw-r--r--src/server/game/World/World.cpp1
-rw-r--r--src/server/game/World/World.h1
16 files changed, 127 insertions, 73 deletions
diff --git a/src/server/game/DataStores/DB2Stores.h b/src/server/game/DataStores/DB2Stores.h
index c508a02f0b1..f8c07ae3432 100644
--- a/src/server/game/DataStores/DB2Stores.h
+++ b/src/server/game/DataStores/DB2Stores.h
@@ -180,6 +180,7 @@ TC_GAME_API extern DB2Storage<ParagonReputationEntry> sParagonRepu
TC_GAME_API extern DB2Storage<PhaseEntry> sPhaseStore;
TC_GAME_API extern DB2Storage<PlayerConditionEntry> sPlayerConditionStore;
TC_GAME_API extern DB2Storage<PowerDisplayEntry> sPowerDisplayStore;
+TC_GAME_API extern DB2Storage<PowerTypeEntry> sPowerTypeStore;
TC_GAME_API extern DB2Storage<PvpTalentEntry> sPvpTalentStore;
TC_GAME_API extern DB2Storage<PvpTalentCategoryEntry> sPvpTalentCategoryStore;
TC_GAME_API extern DB2Storage<PvpTalentSlotUnlockEntry> sPvpTalentSlotUnlockStore;
diff --git a/src/server/game/DataStores/DBCEnums.h b/src/server/game/DataStores/DBCEnums.h
index 637537bf35e..bd8ee99f2be 100644
--- a/src/server/game/DataStores/DBCEnums.h
+++ b/src/server/game/DataStores/DBCEnums.h
@@ -1666,18 +1666,18 @@ enum class PlayerInteractionType : int32
enum class PowerTypeFlags : int16
{
- StopRegenWhileCasting = 0x0001,
+ StopRegenWhileCasting = 0x0001, // NYI
UseRegenInterrupt = 0x0002,
- FillFractionalPowerOnEnergize = 0x0008,
- NoClientPrediction = 0x0010,
+ FillFractionalPowerOnEnergize = 0x0008, // NYI
+ NoClientPrediction = 0x0010, // NYI
UnitsUseDefaultPowerOnInit = 0x0020,
- NotSetToDefaultOnResurrect = 0x0040,
+ NotSetToDefaultOnResurrect = 0x0040, // NYI
IsUsedByNPCs = 0x0080,
- ContinueRegenWhileFatigued = 0x0200,
- RegenAffectedByHaste = 0x0400,
+ ContinueRegenWhileFatigued = 0x0200, // NYI
+ RegenAffectedByHaste = 0x0400, // NYI
SetToMaxOnLevelUp = 0x1000,
- SetToMaxLevelOnInitialLogIn = 0x2000,
- AllowCostModsForPlayers = 0x4000
+ SetToMaxLevelOnInitialLogIn = 0x2000, // NYI
+ AllowCostModsForPlayers = 0x4000 // NYI
};
DEFINE_ENUM_FLAG(PowerTypeFlags);
diff --git a/src/server/game/Entities/Creature/Creature.cpp b/src/server/game/Entities/Creature/Creature.cpp
index d41b0162613..a2f56b7daf2 100644
--- a/src/server/game/Entities/Creature/Creature.cpp
+++ b/src/server/game/Entities/Creature/Creature.cpp
@@ -1563,23 +1563,22 @@ void Creature::UpdateLevelDependantStats()
SetHealth(health);
ResetPlayerDamageReq();
+ SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
+
// mana
- uint32 mana = stats->GenerateMana(cInfo);
- SetCreateMana(mana);
+ Powers powerType = CalculateDisplayPowerType();
+ SetCreateMana(stats->BaseMana);
+ SetStatPctModifier(UnitMods(UNIT_MOD_POWER_START + AsUnderlyingType(powerType)), BASE_PCT, cInfo->ModMana * cInfo->ModManaExtra);
+ SetPowerType(powerType);
- switch (GetClass())
+ if (PowerTypeEntry const* powerTypeEntry = sDB2Manager.GetPowerTypeEntry(powerType))
{
- case CLASS_PALADIN:
- case CLASS_MAGE:
- SetMaxPower(POWER_MANA, mana);
- SetFullPower(POWER_MANA);
- break;
- default: // We don't set max power here, 0 makes power bar hidden
- break;
+ if (powerTypeEntry->GetFlags().HasFlag(PowerTypeFlags::UnitsUseDefaultPowerOnInit))
+ SetPower(powerType, powerTypeEntry->DefaultPower);
+ else
+ SetFullPower(powerType);
}
- SetStatFlatModifier(UNIT_MOD_HEALTH, BASE_VALUE, (float)health);
-
// damage
float basedamage = GetBaseDamageForLevel(level);
@@ -1598,7 +1597,7 @@ void Creature::UpdateLevelDependantStats()
SetStatFlatModifier(UNIT_MOD_ATTACK_POWER, BASE_VALUE, stats->AttackPower);
SetStatFlatModifier(UNIT_MOD_ATTACK_POWER_RANGED, BASE_VALUE, stats->RangedAttackPower);
- float armor = GetBaseArmorForLevel(level); /// @todo Why is this treated as uint32 when it's a float?
+ float armor = GetBaseArmorForLevel(level);
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, armor);
}
diff --git a/src/server/game/Entities/Creature/Creature.h b/src/server/game/Entities/Creature/Creature.h
index 9f1f57904a9..a60701e8f26 100644
--- a/src/server/game/Entities/Creature/Creature.h
+++ b/src/server/game/Entities/Creature/Creature.h
@@ -192,6 +192,7 @@ class TC_GAME_API Creature : public Unit, public GridObject<Creature>, public Ma
bool UpdateEntry(uint32 entry, CreatureData const* data = nullptr, bool updateLevel = true);
+ int32 GetCreatePowerValue(Powers power) const override;
bool UpdateStats(Stats stat) override;
bool UpdateAllStats() override;
void UpdateArmor() override;
diff --git a/src/server/game/Entities/Creature/CreatureData.h b/src/server/game/Entities/Creature/CreatureData.h
index 7044ccaf665..010afc75434 100644
--- a/src/server/game/Entities/Creature/CreatureData.h
+++ b/src/server/game/Entities/Creature/CreatureData.h
@@ -616,15 +616,6 @@ struct TC_GAME_API CreatureBaseStats
uint32 RangedAttackPower;
// Helpers
- uint32 GenerateMana(CreatureTemplate const* info) const
- {
- // Mana can be 0.
- if (!BaseMana)
- return 0;
-
- return uint32(ceil(BaseMana * info->ModMana * info->ModManaExtra));
- }
-
static CreatureBaseStats const* GetBaseStats(uint8 level, uint8 unitClass);
};
diff --git a/src/server/game/Entities/Pet/Pet.cpp b/src/server/game/Entities/Pet/Pet.cpp
index e95740ea408..5fc48d978ec 100644
--- a/src/server/game/Entities/Pet/Pet.cpp
+++ b/src/server/game/Entities/Pet/Pet.cpp
@@ -896,6 +896,8 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
for (uint8 i = SPELL_SCHOOL_HOLY; i < MAX_SPELL_SCHOOL; ++i)
SetStatFlatModifier(UnitMods(UNIT_MOD_RESISTANCE_START + i), BASE_VALUE, float(cinfo->resistance[i]));
+ Powers powerType = CalculateDisplayPowerType();
+
// Health, Mana or Power, Armor
PetLevelInfo const* pInfo = sObjectMgr->GetPetLevelInfo(creature_ID, petlevel);
if (pInfo) // exist in DB
@@ -903,6 +905,8 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
SetCreateHealth(pInfo->health);
SetCreateMana(pInfo->mana);
+ SetStatPctModifier(UnitMods(UNIT_MOD_POWER_START + AsUnderlyingType(powerType)), BASE_PCT, 1.0f);
+
if (pInfo->armor > 0)
SetStatFlatModifier(UNIT_MOD_ARMOR, BASE_VALUE, float(pInfo->armor));
@@ -916,7 +920,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
ApplyLevelScaling();
SetCreateHealth(sDB2Manager.EvaluateExpectedStat(ExpectedStatType::CreatureHealth, petlevel, cinfo->GetHealthScalingExpansion(), m_unitData->ContentTuningID, Classes(cinfo->unit_class)) * cinfo->ModHealth * cinfo->ModHealthExtra * _GetHealthMod(cinfo->rank));
- SetCreateMana(stats->GenerateMana(cinfo));
+ SetCreateMana(stats->BaseMana);
SetCreateStat(STAT_STRENGTH, 22);
SetCreateStat(STAT_AGILITY, 22);
SetCreateStat(STAT_STAMINA, 25);
@@ -924,17 +928,7 @@ bool Guardian::InitStatsForLevel(uint8 petlevel)
}
// Power
- if (petType == HUNTER_PET) // Hunter pets have focus
- SetPowerType(POWER_FOCUS);
- else if (IsPetGhoul() || IsPetAbomination()) // DK pets have energy
- {
- SetPowerType(POWER_ENERGY);
- SetFullPower(POWER_ENERGY);
- }
- else if (IsWarlockPet()) // Warlock pets have energy (since 5.x)
- SetPowerType(POWER_ENERGY);
- else
- SetPowerType(POWER_MANA);
+ SetPowerType(powerType);
// Damage
SetBonusDamage(0);
diff --git a/src/server/game/Entities/Player/Player.cpp b/src/server/game/Entities/Player/Player.cpp
index 56cce2bf0a4..e346b174147 100644
--- a/src/server/game/Entities/Player/Player.cpp
+++ b/src/server/game/Entities/Player/Player.cpp
@@ -167,7 +167,7 @@ Player::Player(WorldSession* session) : Unit(true), m_sceneMgr(this)
if (!GetSession()->HasPermission(rbac::RBAC_PERM_CAN_FILTER_WHISPERS))
SetAcceptWhispers(true);
- m_combatExitTime = 0;
+ m_regenInterruptTimestamp = GameTime::Now();
m_regenTimer = 0;
m_regenTimerCount = 0;
m_foodEmoteTimerCount = 0;
@@ -1780,7 +1780,7 @@ void Player::Regenerate(Powers power)
float addvalue = 0.0f;
if (!IsInCombat())
{
- if (powerType->RegenInterruptTimeMS && GetMSTimeDiffToNow(m_combatExitTime) < uint32(powerType->RegenInterruptTimeMS))
+ if (powerType->GetFlags().HasFlag(PowerTypeFlags::UseRegenInterrupt) && m_regenInterruptTimestamp + Milliseconds(powerType->RegenInterruptTimeMS) < GameTime::Now())
return;
addvalue = (powerType->RegenPeace + m_unitData->PowerRegenFlatModifier[powerIndex]) * 0.001f * m_regenTimer;
@@ -1809,6 +1809,13 @@ void Player::Regenerate(Powers power)
RATE_POWER_ARCANE_CHARGES,
RATE_POWER_FURY,
RATE_POWER_PAIN,
+ RATE_POWER_ESSENCE,
+ MAX_RATES, // runes
+ MAX_RATES, // runes
+ MAX_RATES, // runes
+ MAX_RATES, // alternate
+ MAX_RATES, // alternate
+ MAX_RATES, // alternate
};
if (RatesForPower[power] != MAX_RATES)
@@ -1903,6 +1910,17 @@ void Player::Regenerate(Powers power)
}
}
+void Player::InterruptPowerRegen(Powers power)
+{
+ uint32 powerIndex = GetPowerIndex(power);
+ if (powerIndex == MAX_POWERS || powerIndex >= MAX_POWERS_PER_CLASS)
+ return;
+
+ m_regenInterruptTimestamp = GameTime::Now();
+ m_powerFraction[powerIndex] = 0.0f;
+ SendDirectMessage(WorldPackets::Combat::InterruptPowerRegen(power).Write());
+}
+
void Player::RegenerateHealth()
{
uint32 curValue = GetHealth();
@@ -2382,7 +2400,9 @@ void Player::GiveLevel(uint8 level)
// Only health and mana are set to maximum.
SetFullHealth();
- SetFullPower(POWER_MANA);
+ for (PowerTypeEntry const* powerType : sPowerTypeStore)
+ if (powerType->GetFlags().HasFlag(PowerTypeFlags::SetToMaxOnLevelUp))
+ SetFullPower(Powers(powerType->PowerTypeEnum));
// update level to hunter/summon pet
if (Pet* pet = GetPet())
@@ -25523,7 +25543,7 @@ void Player::AtExitCombat()
{
Unit::AtExitCombat();
UpdatePotionCooldown();
- m_combatExitTime = getMSTime();
+ m_regenInterruptTimestamp = GameTime::Now();
}
float Player::GetBlockPercent(uint8 attackerLevel) const
diff --git a/src/server/game/Entities/Player/Player.h b/src/server/game/Entities/Player/Player.h
index 200b343b9c6..1130e870368 100644
--- a/src/server/game/Entities/Player/Player.h
+++ b/src/server/game/Entities/Player/Player.h
@@ -1747,6 +1747,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
void SendRespecWipeConfirm(ObjectGuid const& guid, uint32 cost, SpecResetType respecType) const;
void RegenerateAll();
void Regenerate(Powers power);
+ void InterruptPowerRegen(Powers power);
void RegenerateHealth();
void setRegenTimerCount(uint32 time) {m_regenTimerCount = time;}
void setWeaponChangeTimer(uint32 time) {m_weaponChangeTimer = time;}
@@ -2875,7 +2876,7 @@ class TC_GAME_API Player : public Unit, public GridObject<Player>
protected:
// Gamemaster whisper whitelist
GuidList WhisperList;
- uint32 m_combatExitTime;
+ TimePoint m_regenInterruptTimestamp;
uint32 m_regenTimerCount;
uint32 m_foodEmoteTimerCount;
float m_powerFraction[MAX_POWERS_PER_CLASS];
diff --git a/src/server/game/Entities/Unit/StatSystem.cpp b/src/server/game/Entities/Unit/StatSystem.cpp
index 2fe2924702b..2e1f248ecc7 100644
--- a/src/server/game/Entities/Unit/StatSystem.cpp
+++ b/src/server/game/Entities/Unit/StatSystem.cpp
@@ -86,6 +86,17 @@ void Unit::UpdateDamagePhysical(WeaponAttackType attType)
}
}
+int32 Unit::GetCreatePowerValue(Powers power) const
+{
+ if (power == POWER_MANA)
+ return GetCreateMana();
+
+ if (PowerTypeEntry const* powerType = sDB2Manager.GetPowerTypeEntry(power))
+ return powerType->MaxBasePower;
+
+ return 0;
+}
+
/*#######################################
######## ########
######## PLAYERS STAT SYSTEM ########
@@ -874,6 +885,15 @@ void Player::_RemoveAllStatBonuses()
######## ########
#######################################*/
+int32 Creature::GetCreatePowerValue(Powers power) const
+{
+ if (PowerTypeEntry const* powerType = sDB2Manager.GetPowerTypeEntry(power))
+ if (!powerType->GetFlags().HasFlag(PowerTypeFlags::IsUsedByNPCs))
+ return 0;
+
+ return Unit::GetCreatePowerValue(power);
+}
+
bool Creature::UpdateStats(Stats /*stat*/)
{
return true;
@@ -910,10 +930,21 @@ uint32 Creature::GetPowerIndex(Powers power) const
{
if (power == GetPowerType())
return 0;
- if (power == POWER_ALTERNATE_POWER)
- return 1;
- if (power == POWER_COMBO_POINTS)
- return 2;
+ switch (power)
+ {
+ case POWER_COMBO_POINTS:
+ return 2;
+ case POWER_ALTERNATE_POWER:
+ return 1;
+ case POWER_ALTERNATE_QUEST:
+ return 3;
+ case POWER_ALTERNATE_ENCOUNTER:
+ return 4;
+ case POWER_ALTERNATE_MOUNT:
+ return 5;
+ default:
+ break;
+ }
return MAX_POWERS;
}
diff --git a/src/server/game/Entities/Unit/Unit.cpp b/src/server/game/Entities/Unit/Unit.cpp
index 91247e8166a..98fd0ff18a2 100644
--- a/src/server/game/Entities/Unit/Unit.cpp
+++ b/src/server/game/Entities/Unit/Unit.cpp
@@ -5472,7 +5472,7 @@ void Unit::SetPowerType(Powers new_powertype, bool sendUpdate/* = true*/)
}
}
-void Unit::UpdateDisplayPower()
+Powers Unit::CalculateDisplayPowerType() const
{
Powers displayPower = POWER_MANA;
switch (GetShapeshiftForm())
@@ -5496,22 +5496,18 @@ void Unit::UpdateDisplayPower()
AuraEffect const* powerTypeAura = powerTypeAuras.front();
displayPower = Powers(powerTypeAura->GetMiscValue());
}
- else if (GetTypeId() == TYPEID_PLAYER)
+ else
{
ChrClassesEntry const* cEntry = sChrClassesStore.LookupEntry(GetClass());
if (cEntry && cEntry->DisplayPower < MAX_POWERS)
displayPower = Powers(cEntry->DisplayPower);
- }
- else if (GetTypeId() == TYPEID_UNIT)
- {
+
if (Vehicle* vehicle = GetVehicleKit())
{
if (PowerDisplayEntry const* powerDisplay = sPowerDisplayStore.LookupEntry(vehicle->GetVehicleInfo()->PowerDisplayID[0]))
displayPower = Powers(powerDisplay->ActualType);
- else if (GetClass() == CLASS_ROGUE)
- displayPower = POWER_ENERGY;
}
- else if (Pet* pet = ToPet())
+ else if (Pet const* pet = ToPet())
{
if (pet->getPetType() == HUNTER_PET) // Hunter pets have focus
displayPower = POWER_FOCUS;
@@ -5523,7 +5519,12 @@ void Unit::UpdateDisplayPower()
}
}
- SetPowerType(displayPower);
+ return displayPower;
+}
+
+void Unit::UpdateDisplayPower()
+{
+ SetPowerType(CalculateDisplayPowerType());
}
void Unit::SetSheath(SheathState sheathed)
@@ -6496,6 +6497,11 @@ void Unit::SendEnergizeSpellLog(Unit* victim, uint32 spellID, int32 damage, int3
void Unit::EnergizeBySpell(Unit* victim, SpellInfo const* spellInfo, int32 damage, Powers powerType)
{
+ if (Player* player = victim->ToPlayer())
+ if (PowerTypeEntry const* powerTypeEntry = sDB2Manager.GetPowerTypeEntry(powerType))
+ if (powerTypeEntry->GetFlags().HasFlag(PowerTypeFlags::UseRegenInterrupt))
+ player->InterruptPowerRegen(powerType);
+
int32 gain = victim->ModifyPower(powerType, damage, false);
int32 overEnergize = damage - gain;
victim->GetThreatManager().ForwardThreatForAssistingMe(this, float(damage) / 2, spellInfo, true);
@@ -9310,17 +9316,6 @@ void Unit::TriggerOnPowerChangeAuras(Powers power, int32 oldVal, int32 newVal)
}
}
-int32 Unit::GetCreatePowerValue(Powers power) const
-{
- if (power == POWER_MANA)
- return GetCreateMana();
-
- if (PowerTypeEntry const* powerType = sDB2Manager.GetPowerTypeEntry(power))
- return powerType->MaxBasePower;
-
- return 0;
-}
-
void Unit::AIUpdateTick(uint32 diff)
{
if (UnitAI* ai = GetAI())
diff --git a/src/server/game/Entities/Unit/Unit.h b/src/server/game/Entities/Unit/Unit.h
index 06f8076df6d..d12fbda04bd 100644
--- a/src/server/game/Entities/Unit/Unit.h
+++ b/src/server/game/Entities/Unit/Unit.h
@@ -915,6 +915,7 @@ class TC_GAME_API Unit : public WorldObject
Powers GetPowerType() const { return Powers(*m_unitData->DisplayPower); }
void SetPowerType(Powers power, bool sendUpdate = true);
void SetOverrideDisplayPowerId(uint32 powerDisplayId) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::OverrideDisplayPowerID), powerDisplayId); }
+ Powers CalculateDisplayPowerType() const;
void UpdateDisplayPower();
int32 GetPower(Powers power) const;
int32 GetMinPower(Powers power) const { return power == POWER_LUNAR_POWER ? -100 : 0; }
@@ -1490,7 +1491,7 @@ class TC_GAME_API Unit : public WorldObject
uint32 GetCreateHealth() const { return m_unitData->BaseHealth; }
void SetCreateMana(uint32 val) { SetUpdateFieldValue(m_values.ModifyValue(&Unit::m_unitData).ModifyValue(&UF::UnitData::BaseMana), val); }
uint32 GetCreateMana() const { return m_unitData->BaseMana; }
- int32 GetCreatePowerValue(Powers power) const;
+ virtual int32 GetCreatePowerValue(Powers power) const;
float GetPosStat(Stats stat) const { return m_unitData->StatPosBuff[stat]; }
float GetNegStat(Stats stat) const { return m_unitData->StatNegBuff[stat]; }
float GetCreateStat(Stats stat) const { return m_createStats[stat]; }
diff --git a/src/server/game/Server/Packets/CombatPackets.cpp b/src/server/game/Server/Packets/CombatPackets.cpp
index 97d56755cba..d662128556f 100644
--- a/src/server/game/Server/Packets/CombatPackets.cpp
+++ b/src/server/game/Server/Packets/CombatPackets.cpp
@@ -114,6 +114,13 @@ WorldPacket const* WorldPackets::Combat::PowerUpdate::Write()
return &_worldPacket;
}
+WorldPacket const* WorldPackets::Combat::InterruptPowerRegen::Write()
+{
+ _worldPacket << int32(PowerType);
+
+ return &_worldPacket;
+}
+
void WorldPackets::Combat::SetSheathed::Read()
{
_worldPacket >> CurrentSheathState;
diff --git a/src/server/game/Server/Packets/CombatPackets.h b/src/server/game/Server/Packets/CombatPackets.h
index 6163fb81aca..4aaa57ceba9 100644
--- a/src/server/game/Server/Packets/CombatPackets.h
+++ b/src/server/game/Server/Packets/CombatPackets.h
@@ -22,6 +22,7 @@
#include "ObjectGuid.h"
class Unit;
+enum Powers : int8;
namespace WorldPackets
{
@@ -166,6 +167,16 @@ namespace WorldPackets
std::vector<PowerUpdatePower> Powers;
};
+ class InterruptPowerRegen final : public ServerPacket
+ {
+ public:
+ explicit InterruptPowerRegen(Powers powerType) : ServerPacket(SMSG_INTERRUPT_POWER_REGEN, 4), PowerType(powerType) { }
+
+ WorldPacket const* Write() override;
+
+ Powers PowerType;
+ };
+
class SetSheathed final : public ClientPacket
{
public:
diff --git a/src/server/game/Server/Protocol/Opcodes.cpp b/src/server/game/Server/Protocol/Opcodes.cpp
index f2a0db0a797..93c375257fa 100644
--- a/src/server/game/Server/Protocol/Opcodes.cpp
+++ b/src/server/game/Server/Protocol/Opcodes.cpp
@@ -1528,7 +1528,7 @@ void OpcodeTable::Initialize()
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_RESET_FAILED, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INSTANCE_SAVE_CREATED, STATUS_NEVER, CONNECTION_TYPE_REALM);
- DEFINE_SERVER_OPCODE_HANDLER(SMSG_INTERRUPT_POWER_REGEN, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
+ DEFINE_SERVER_OPCODE_HANDLER(SMSG_INTERRUPT_POWER_REGEN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INVALIDATE_PAGE_TEXT, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INVALIDATE_PLAYER, STATUS_NEVER, CONNECTION_TYPE_REALM);
DEFINE_SERVER_OPCODE_HANDLER(SMSG_INVALID_PROMOTION_CODE, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
diff --git a/src/server/game/World/World.cpp b/src/server/game/World/World.cpp
index d849a261698..3bf7c0a6c58 100644
--- a/src/server/game/World/World.cpp
+++ b/src/server/game/World/World.cpp
@@ -631,6 +631,7 @@ void World::LoadConfigSettings(bool reload)
setRegenRate(RATE_POWER_ARCANE_CHARGES, "Rate.ArcaneCharges.Loss");
setRegenRate(RATE_POWER_FURY, "Rate.Fury.Loss");
setRegenRate(RATE_POWER_PAIN, "Rate.Pain.Loss");
+ setRegenRate(RATE_POWER_ESSENCE, "Rate.Essence.Loss");
rate_values[RATE_SKILL_DISCOVERY] = sConfigMgr->GetFloatDefault("Rate.Skill.Discovery", 1.0f);
rate_values[RATE_DROP_ITEM_POOR] = sConfigMgr->GetFloatDefault("Rate.Drop.Item.Poor", 1.0f);
diff --git a/src/server/game/World/World.h b/src/server/game/World/World.h
index 3be26d65a9c..cb2973cc6a8 100644
--- a/src/server/game/World/World.h
+++ b/src/server/game/World/World.h
@@ -463,6 +463,7 @@ enum Rates
RATE_POWER_ARCANE_CHARGES,
RATE_POWER_FURY,
RATE_POWER_PAIN,
+ RATE_POWER_ESSENCE,
RATE_SKILL_DISCOVERY,
RATE_DROP_ITEM_POOR,
RATE_DROP_ITEM_NORMAL,