mirror of
https://github.com/TrinityCore/TrinityCore.git
synced 2026-01-17 08:00:48 +01:00
Core/Auras: Implemented SPELL_AURA_MOD_RECOVERY_RATE and SPELL_AURA_MOD_RECOVERY_RATE_BY_SPELL_LABEL
(cherry picked from commit 0c19893800)
# Conflicts:
# src/server/game/Server/Packets/SpellPackets.cpp
# src/server/scripts/Spells/spell_shaman.cpp
This commit is contained in:
@@ -610,6 +610,15 @@ WorldPacket const* ModifyCooldown::Write()
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
WorldPacket const* UpdateCooldown::Write()
|
||||
{
|
||||
_worldPacket << int32(SpellID);
|
||||
_worldPacket << float(ModChange);
|
||||
_worldPacket << float(ModRate);
|
||||
|
||||
return &_worldPacket;
|
||||
}
|
||||
|
||||
ByteBuffer& operator<<(ByteBuffer& data, SpellCooldownStruct const& cooldown)
|
||||
{
|
||||
data << uint32(cooldown.SrecID);
|
||||
|
||||
@@ -542,11 +542,23 @@ namespace WorldPackets
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
bool IsPet = false;
|
||||
bool WithoutCategoryCooldown = false;
|
||||
bool SkipCategory = false;
|
||||
int32 DeltaTime = 0;
|
||||
int32 SpellID = 0;
|
||||
};
|
||||
|
||||
class UpdateCooldown final : public ServerPacket
|
||||
{
|
||||
public:
|
||||
UpdateCooldown() : ServerPacket(SMSG_UPDATE_COOLDOWN, 4 + 4 + 4) { }
|
||||
|
||||
WorldPacket const* Write() override;
|
||||
|
||||
int32 SpellID = 0;
|
||||
float ModChange = 1.0f;
|
||||
float ModRate = 1.0f;
|
||||
};
|
||||
|
||||
struct SpellCooldownStruct
|
||||
{
|
||||
SpellCooldownStruct() { }
|
||||
|
||||
@@ -1896,7 +1896,7 @@ void OpcodeTable::InitializeServerOpcodes()
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_CELESTIAL_BODY, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_CHARACTER_FLAGS, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_CHARGE_CATEGORY_COOLDOWN, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_COOLDOWN, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_COOLDOWN, STATUS_NEVER, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_CRAFTING_NPC_RECIPES, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_DAILY_MISSION_COUNTER, STATUS_UNHANDLED, CONNECTION_TYPE_INSTANCE);
|
||||
DEFINE_SERVER_OPCODE_HANDLER(SMSG_UPDATE_EXPANSION_LEVEL, STATUS_UNHANDLED, CONNECTION_TYPE_REALM);
|
||||
|
||||
@@ -235,7 +235,7 @@ enum AuraType : uint32
|
||||
SPELL_AURA_MOD_RANGED_HASTE = 140,
|
||||
SPELL_AURA_141 = 141, // old SPELL_AURA_MOD_RANGED_AMMO_HASTE, unused now
|
||||
SPELL_AURA_MOD_BASE_RESISTANCE_PCT = 142,
|
||||
SPELL_AURA_MOD_RECOVERY_RATE_BY_SPELL_LABEL = 143, // NYI
|
||||
SPELL_AURA_MOD_RECOVERY_RATE_BY_SPELL_LABEL = 143,
|
||||
SPELL_AURA_SAFE_FALL = 144,
|
||||
SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT2 = 145,
|
||||
SPELL_AURA_ALLOW_TAME_PET_TYPE = 146,
|
||||
|
||||
@@ -212,7 +212,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
|
||||
&AuraEffect::HandleAuraModRangedHaste, //140 SPELL_AURA_MOD_RANGED_HASTE
|
||||
&AuraEffect::HandleUnused, //141 SPELL_AURA_141
|
||||
&AuraEffect::HandleAuraModBaseResistancePCT, //142 SPELL_AURA_MOD_BASE_RESISTANCE_PCT
|
||||
&AuraEffect::HandleNULL, //143 SPELL_AURA_MOD_RECOVERY_RATE_BY_SPELL_LABEL
|
||||
&AuraEffect::HandleModRecoveryRateBySpellLabel, //143 SPELL_AURA_MOD_RECOVERY_RATE_BY_SPELL_LABEL also implemented in SpellHistory::StartCooldown
|
||||
&AuraEffect::HandleNoImmediateEffect, //144 SPELL_AURA_SAFE_FALL implemented in WorldSession::HandleMovementOpcodes
|
||||
&AuraEffect::HandleAuraModIncreaseHealthPercent, //145 SPELL_AURA_MOD_INCREASE_HEALTH_PERCENT2
|
||||
&AuraEffect::HandleNoImmediateEffect, //146 SPELL_AURA_ALLOW_TAME_PET_TYPE
|
||||
@@ -355,7 +355,7 @@ NonDefaultConstructible<pAuraEffectHandler> AuraEffectHandler[TOTAL_AURAS]=
|
||||
&AuraEffect::HandleNoImmediateEffect, //283 SPELL_AURA_MOD_HEALING_RECEIVED implemented in Unit::SpellHealingBonus
|
||||
&AuraEffect::HandleAuraLinked, //284 SPELL_AURA_LINKED
|
||||
&AuraEffect::HandleAuraLinked, //285 SPELL_AURA_LINKED_2
|
||||
&AuraEffect::HandleNULL, //286 SPELL_AURA_MOD_RECOVERY_RATE
|
||||
&AuraEffect::HandleModRecoveryRate, //286 SPELL_AURA_MOD_RECOVERY_RATE also implemented in SpellHistory::StartCooldown
|
||||
&AuraEffect::HandleNoImmediateEffect, //287 SPELL_AURA_DEFLECT_SPELLS implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult
|
||||
&AuraEffect::HandleNoImmediateEffect, //288 SPELL_AURA_IGNORE_HIT_DIRECTION implemented in Unit::MagicSpellHitResult and Unit::MeleeSpellHitResult Unit::RollMeleeOutcomeAgainst
|
||||
&AuraEffect::HandleNoImmediateEffect, //289 SPELL_AURA_PREVENT_DURABILITY_LOSS implemented in Player::DurabilityPointsLoss
|
||||
@@ -6174,6 +6174,33 @@ void AuraEffect::HandleModSpellCategoryCooldown(AuraApplication const* aurApp, u
|
||||
target->RemoveSpellCategoryCooldownMod(GetMiscValue(), GetAmount());
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModRecoveryRate(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
{
|
||||
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
|
||||
return;
|
||||
|
||||
float rate = 100.0f / (std::max<float>(GetAmount(), -99.0f) + 100.0f);
|
||||
|
||||
aurApp->GetTarget()->GetSpellHistory()->UpdateCooldownRecoveryRate([&](SpellHistory::CooldownEntry const& cooldown)
|
||||
{
|
||||
return IsAffectingSpell(sSpellMgr->GetSpellInfo(cooldown.SpellId, DIFFICULTY_NONE));
|
||||
}, rate, apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleModRecoveryRateBySpellLabel(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
{
|
||||
if (!(mode & AURA_EFFECT_HANDLE_CHANGE_AMOUNT_MASK))
|
||||
return;
|
||||
|
||||
float rate = 100.0f / (std::max<float>(GetAmount(), -99.0f) + 100.0f);
|
||||
|
||||
aurApp->GetTarget()->GetSpellHistory()->UpdateCooldownRecoveryRate([&](SpellHistory::CooldownEntry const& cooldown)
|
||||
{
|
||||
SpellInfo const* spellInfo = sSpellMgr->AssertSpellInfo(cooldown.SpellId, DIFFICULTY_NONE);
|
||||
return spellInfo->HasLabel(GetMiscValue()) || (GetMiscValueB() && spellInfo->HasLabel(GetMiscValueB()));
|
||||
}, rate, apply);
|
||||
}
|
||||
|
||||
void AuraEffect::HandleShowConfirmationPrompt(AuraApplication const* aurApp, uint8 mode, bool apply) const
|
||||
{
|
||||
if (!(mode & AURA_EFFECT_HANDLE_REAL))
|
||||
|
||||
@@ -324,6 +324,8 @@ class TC_GAME_API AuraEffect
|
||||
void HandleAuraForceWeather(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleEnableAltPower(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleModSpellCategoryCooldown(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleModRecoveryRate(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleModRecoveryRateBySpellLabel(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleShowConfirmationPrompt(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleOverridePetSpecs(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
void HandleAllowUsingGameobjectsWhileMounted(AuraApplication const* aurApp, uint8 mode, bool apply) const;
|
||||
|
||||
@@ -27,6 +27,7 @@
|
||||
#include "PetPackets.h"
|
||||
#include "Player.h"
|
||||
#include "Spell.h"
|
||||
#include "SpellAuraEffects.h"
|
||||
#include "SpellInfo.h"
|
||||
#include "SpellMgr.h"
|
||||
#include "SpellPackets.h"
|
||||
@@ -422,6 +423,8 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
|
||||
{
|
||||
if (!forcedCooldown)
|
||||
{
|
||||
Duration baseCooldown = cooldown;
|
||||
|
||||
// Now we have cooldown data (if found any), time to apply mods
|
||||
if (Player* modOwner = _owner->GetSpellModOwner())
|
||||
{
|
||||
@@ -451,6 +454,34 @@ void SpellHistory::StartCooldown(SpellInfo const* spellInfo, uint32 itemId, Spel
|
||||
categoryCooldown = Duration(int64(categoryCooldown.count() * _owner->m_unitData->ModHasteRegen));
|
||||
}
|
||||
|
||||
{
|
||||
auto calcRecoveryRate = [&](AuraEffect const* modRecoveryRate)
|
||||
{
|
||||
float rate = 100.0f / (std::max<float>(modRecoveryRate->GetAmount(), -99.0f) + 100.0f);
|
||||
if (baseCooldown <= 1h
|
||||
&& !spellInfo->HasAttribute(SPELL_ATTR6_IGNORE_FOR_MOD_TIME_RATE)
|
||||
&& !modRecoveryRate->GetSpellEffectInfo().EffectAttributes.HasFlag(SpellEffectAttributes::IgnoreDuringCooldownTimeRateCalculation))
|
||||
rate *= *_owner->m_unitData->ModTimeRate;
|
||||
|
||||
return rate;
|
||||
};
|
||||
|
||||
float recoveryRate = 1.0f;
|
||||
for (AuraEffect const* modRecoveryRate : _owner->GetAuraEffectsByType(SPELL_AURA_MOD_RECOVERY_RATE))
|
||||
if (modRecoveryRate->IsAffectingSpell(spellInfo))
|
||||
recoveryRate *= calcRecoveryRate(modRecoveryRate);
|
||||
|
||||
for (AuraEffect const* modRecoveryRate : _owner->GetAuraEffectsByType(SPELL_AURA_MOD_RECOVERY_RATE_BY_SPELL_LABEL))
|
||||
if (spellInfo->HasLabel(modRecoveryRate->GetMiscValue()) || (modRecoveryRate->GetMiscValueB() && spellInfo->HasLabel(modRecoveryRate->GetMiscValueB())))
|
||||
recoveryRate *= calcRecoveryRate(modRecoveryRate);
|
||||
|
||||
if (recoveryRate > 0.0f)
|
||||
{
|
||||
cooldown = Duration(int64(cooldown.count() * recoveryRate));
|
||||
categoryCooldown = Duration(int64(categoryCooldown.count() * recoveryRate));
|
||||
}
|
||||
}
|
||||
|
||||
if (int32 cooldownMod = _owner->GetTotalAuraModifier(SPELL_AURA_MOD_COOLDOWN))
|
||||
{
|
||||
// Apply SPELL_AURA_MOD_COOLDOWN only to own spells
|
||||
@@ -591,7 +622,7 @@ void SpellHistory::ModifySpellCooldown(CooldownStorageType::iterator& itr, Durat
|
||||
modifyCooldown.IsPet = _owner != playerOwner;
|
||||
modifyCooldown.SpellID = itr->second.SpellId;
|
||||
modifyCooldown.DeltaTime = duration_cast<Milliseconds>(cooldownMod).count();
|
||||
modifyCooldown.WithoutCategoryCooldown = withoutCategoryCooldown;
|
||||
modifyCooldown.SkipCategory = withoutCategoryCooldown;
|
||||
playerOwner->SendDirectMessage(modifyCooldown.Write());
|
||||
}
|
||||
|
||||
@@ -599,6 +630,30 @@ void SpellHistory::ModifySpellCooldown(CooldownStorageType::iterator& itr, Durat
|
||||
itr = EraseCooldown(itr);
|
||||
}
|
||||
|
||||
void SpellHistory::UpdateCooldownRecoveryRate(CooldownStorageType::iterator& itr, float modChange, bool apply)
|
||||
{
|
||||
if (modChange <= 0.0f)
|
||||
return;
|
||||
|
||||
if (!apply)
|
||||
modChange = 1.0f / modChange;
|
||||
|
||||
TimePoint now = time_point_cast<Duration>(GameTime::GetTime<Clock>());
|
||||
|
||||
itr->second.CooldownEnd = now + duration_cast<Duration>((itr->second.CooldownEnd - now) * modChange);
|
||||
|
||||
if (itr->second.CategoryId)
|
||||
itr->second.CategoryEnd = now + duration_cast<Duration>((itr->second.CategoryEnd - now) * modChange);
|
||||
|
||||
if (Player* playerOwner = GetPlayerOwner())
|
||||
{
|
||||
WorldPackets::Spells::UpdateCooldown updateCooldown;
|
||||
updateCooldown.SpellID = itr->second.SpellId;
|
||||
updateCooldown.ModChange = modChange;
|
||||
playerOwner->SendDirectMessage(updateCooldown.Write());
|
||||
}
|
||||
}
|
||||
|
||||
void SpellHistory::ModifyCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown)
|
||||
{
|
||||
if (SpellInfo const* spellInfo = sSpellMgr->GetSpellInfo(spellId, _owner->GetMap()->GetDifficultyID()))
|
||||
|
||||
@@ -139,6 +139,16 @@ public:
|
||||
}
|
||||
}
|
||||
|
||||
template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
|
||||
void UpdateCooldownRecoveryRate(Predicate&& predicate, float modChange, bool apply)
|
||||
{
|
||||
for (auto itr = _spellCooldowns.begin(); itr != _spellCooldowns.end(); ++itr)
|
||||
{
|
||||
if (std::forward<Predicate>(predicate)(itr->second))
|
||||
UpdateCooldownRecoveryRate(itr, modChange, apply);
|
||||
}
|
||||
}
|
||||
|
||||
void ResetCooldown(uint32 spellId, bool update = false);
|
||||
template <Trinity::invocable_r<bool, CooldownEntry const&> Predicate>
|
||||
void ResetCooldowns(Predicate&& predicate, bool update = false)
|
||||
@@ -200,6 +210,7 @@ private:
|
||||
Player* GetPlayerOwner() const;
|
||||
void ModifySpellCooldown(uint32 spellId, Duration cooldownMod, bool withoutCategoryCooldown);
|
||||
void ModifySpellCooldown(CooldownStorageType::iterator& itr, Duration cooldownMod, bool withoutCategoryCooldown);
|
||||
void UpdateCooldownRecoveryRate(CooldownStorageType::iterator& itr, float modChange, bool apply);
|
||||
void ResetCooldown(CooldownStorageType::iterator& itr, bool update = false);
|
||||
void SendClearCooldowns(std::vector<int32> const& cooldowns) const;
|
||||
CooldownStorageType::iterator EraseCooldown(CooldownStorageType::iterator itr)
|
||||
|
||||
Reference in New Issue
Block a user