aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorShauren <shauren.trinity@gmail.com>2024-05-04 13:06:17 +0200
committerShauren <shauren.trinity@gmail.com>2024-05-04 13:06:17 +0200
commit240b7e58d81688e31d84511db4afd6229337c9e9 (patch)
treeadff9ae92fc6bbf50b93879deaac352952fb1bcc /src
parent2aedd8ecdb16a8c72ff89c6c09ad99fff23609b1 (diff)
Core/Spells: Refund power cost when cancelling empower spells
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Spells/Spell.cpp106
-rw-r--r--src/server/game/Spells/Spell.h2
2 files changed, 78 insertions, 30 deletions
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index fd354cdcfb1..8304e18df69 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -4427,6 +4427,13 @@ void Spell::finish(SpellCastResult result)
Unit::ProcSkillsAndAuras(unitCaster, nullptr, PROC_FLAG_CAST_ENDED, PROC_FLAG_NONE, PROC_SPELL_TYPE_MASK_ALL, PROC_SPELL_PHASE_NONE, PROC_HIT_NONE, this, nullptr, nullptr);
+ if (IsEmpowerSpell())
+ {
+ // Empower spells trigger gcd at the end of cast instead of at start
+ if (SpellInfo const* gcd = sSpellMgr->GetSpellInfo(SPELL_EMPOWER_HARDCODED_GCD, DIFFICULTY_NONE))
+ unitCaster->GetSpellHistory()->AddGlobalCooldown(gcd, Milliseconds(gcd->StartRecoveryTime));
+ }
+
if (result != SPELL_CAST_OK)
{
// on failure (or manual cancel) send TraitConfigCommitFailed to revert talent UI saved config selection
@@ -4435,7 +4442,10 @@ void Spell::finish(SpellCastResult result)
m_caster->ToPlayer()->SendDirectMessage(WorldPackets::Traits::TraitConfigCommitFailed(traitConfig->ID).Write());
if (IsEmpowerSpell())
+ {
unitCaster->GetSpellHistory()->ResetCooldown(m_spellInfo->Id, true);
+ RefundPower();
+ }
return;
}
@@ -4466,13 +4476,6 @@ void Spell::finish(SpellCastResult result)
// Stop Attack for some spells
if (m_spellInfo->HasAttribute(SPELL_ATTR0_CANCELS_AUTO_ATTACK_COMBAT))
unitCaster->AttackStop();
-
- if (IsEmpowerSpell())
- {
- // Empower spells trigger gcd at the end of cast instead of at start
- if (SpellInfo const* gcd = sSpellMgr->GetSpellInfo(SPELL_EMPOWER_HARDCODED_GCD, DIFFICULTY_NONE))
- unitCaster->GetSpellHistory()->AddGlobalCooldown(gcd, Milliseconds(gcd->StartRecoveryTime));
- }
}
template<class T>
@@ -5537,30 +5540,27 @@ void Spell::TakePower()
return;
}
+ bool hit = true;
+ if (unitCaster->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISCOUNT_POWER_ON_MISS))
+ {
+ ObjectGuid targetGUID = m_targets.GetUnitTargetGUID();
+ if (!targetGUID.IsEmpty())
+ hit = std::ranges::any_of(m_UniqueTargetInfo, [&](TargetInfo const& targetInfo) { return targetInfo.TargetGUID == targetGUID && targetInfo.MissCondition == SPELL_MISS_NONE; });
+ }
+ }
+
for (SpellPowerCost& cost : m_powerCost)
{
- Powers powerType = Powers(cost.Power);
- bool hit = true;
- if (unitCaster->GetTypeId() == TYPEID_PLAYER)
+ if (!hit)
{
- if (m_spellInfo->HasAttribute(SPELL_ATTR1_DISCOUNT_POWER_ON_MISS))
- {
- ObjectGuid targetGUID = m_targets.GetUnitTargetGUID();
- if (!targetGUID.IsEmpty())
- {
- auto ihit = std::find_if(std::begin(m_UniqueTargetInfo), std::end(m_UniqueTargetInfo), [&](TargetInfo const& targetInfo) { return targetInfo.TargetGUID == targetGUID && targetInfo.MissCondition != SPELL_MISS_NONE; });
- if (ihit != std::end(m_UniqueTargetInfo))
- {
- hit = false;
- //lower spell cost on fail (by talent aura)
- if (Player* modOwner = unitCaster->GetSpellModOwner())
- modOwner->ApplySpellMod(m_spellInfo, SpellModOp::PowerCostOnMiss, cost.Amount);
- }
- }
- }
+ //lower spell cost on fail (by talent aura)
+ if (Player* modOwner = unitCaster->GetSpellModOwner())
+ modOwner->ApplySpellMod(m_spellInfo, SpellModOp::PowerCostOnMiss, cost.Amount);
}
- if (powerType == POWER_RUNES)
+ if (cost.Power == POWER_RUNES)
{
TakeRunePower(hit);
continue;
@@ -5570,19 +5570,52 @@ void Spell::TakePower()
continue;
// health as power used
- if (powerType == POWER_HEALTH)
+ if (cost.Power == POWER_HEALTH)
{
unitCaster->ModifyHealth(-cost.Amount);
continue;
}
- if (powerType >= MAX_POWERS)
+ unitCaster->ModifyPower(cost.Power, -cost.Amount);
+ }
+}
+
+void Spell::RefundPower()
+{
+ // GameObjects don't use power
+ Unit* unitCaster = m_caster->ToUnit();
+ if (!unitCaster)
+ return;
+
+ if (m_CastItem || m_triggeredByAuraSpell)
+ return;
+
+ //Don't take power if the spell is cast while .cheat power is enabled.
+ if (unitCaster->GetTypeId() == TYPEID_PLAYER)
+ {
+ if (unitCaster->ToPlayer()->GetCommandStatus(CHEAT_POWER))
+ return;
+ }
+
+ for (SpellPowerCost& cost : m_powerCost)
+ {
+ if (cost.Power == POWER_RUNES)
+ {
+ RefundRunePower();
+ continue;
+ }
+
+ if (!cost.Amount)
+ continue;
+
+ // health as power used
+ if (cost.Power == POWER_HEALTH)
{
- TC_LOG_ERROR("spells", "Spell::TakePower: Unknown power type '{}'", powerType);
+ unitCaster->ModifyHealth(cost.Amount);
continue;
}
- unitCaster->ModifyPower(powerType, -cost.Amount);
+ unitCaster->ModifyPower(cost.Power, cost.Amount);
}
}
@@ -5637,6 +5670,19 @@ void Spell::TakeRunePower(bool didHit)
}
}
+void Spell::RefundRunePower()
+{
+ if (m_caster->GetTypeId() != TYPEID_PLAYER || m_caster->ToPlayer()->GetClass() != CLASS_DEATH_KNIGHT)
+ return;
+
+ Player* player = m_caster->ToPlayer();
+
+ // restore old rune state
+ for (int32 i = 0; i < player->GetMaxPower(POWER_RUNES); ++i)
+ if (m_runesState & (1 << i))
+ player->SetRuneCooldown(i, 0);
+}
+
void Spell::TakeReagents()
{
if (m_caster->GetTypeId() != TYPEID_PLAYER)
diff --git a/src/server/game/Spells/Spell.h b/src/server/game/Spells/Spell.h
index 8f25f5844dd..02f10b26413 100644
--- a/src/server/game/Spells/Spell.h
+++ b/src/server/game/Spells/Spell.h
@@ -478,8 +478,10 @@ class TC_GAME_API Spell
void cast(bool skipCheck = false);
void finish(SpellCastResult result = SPELL_CAST_OK);
void TakePower();
+ void RefundPower();
void TakeRunePower(bool didHit);
+ void RefundRunePower();
void TakeReagents();
void TakeCastItem();