aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/server/game/Entities/Object/Object.cpp47
-rw-r--r--src/server/game/Entities/Object/Object.h3
-rw-r--r--src/server/game/Spells/Auras/SpellAuraEffects.cpp2
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.cpp6
-rw-r--r--src/server/game/Spells/Auras/SpellAuras.h2
-rw-r--r--src/server/game/Spells/Spell.cpp2
-rw-r--r--src/server/game/Spells/SpellInfo.cpp29
7 files changed, 48 insertions, 43 deletions
diff --git a/src/server/game/Entities/Object/Object.cpp b/src/server/game/Entities/Object/Object.cpp
index 9a0a941a98a..855138c3c6f 100644
--- a/src/server/game/Entities/Object/Object.cpp
+++ b/src/server/game/Entities/Object/Object.cpp
@@ -2346,26 +2346,43 @@ double WorldObject::ApplyEffectModifiers(SpellInfo const* spellInfo, uint8 effIn
return value;
}
-int32 WorldObject::CalcSpellDuration(SpellInfo const* spellInfo) const
+int32 WorldObject::CalcSpellDuration(SpellInfo const* spellInfo, std::vector<SpellPowerCost> const* powerCosts) const
{
- int32 comboPoints = 0;
- int32 maxComboPoints = 5;
- if (Unit const* unit = ToUnit())
- {
- comboPoints = unit->GetPower(POWER_COMBO_POINTS);
- maxComboPoints = unit->GetMaxPower(POWER_COMBO_POINTS);
- }
-
int32 minduration = spellInfo->GetDuration();
+ if (minduration <= 0)
+ return minduration;
+
int32 maxduration = spellInfo->GetMaxDuration();
+ if (minduration == maxduration)
+ return minduration;
- int32 duration;
- if (comboPoints && minduration != -1 && minduration != maxduration)
- duration = minduration + int32((maxduration - minduration) * comboPoints / maxComboPoints);
- else
- duration = minduration;
+ Unit const* unit = ToUnit();
+ if (!unit)
+ return minduration;
+
+ if (!powerCosts)
+ return minduration;
+
+ // we want only baseline cost here
+ auto itr = std::find_if(spellInfo->PowerCosts.begin(), spellInfo->PowerCosts.end(), [=](SpellPowerEntry const* powerEntry)
+ {
+ return powerEntry && powerEntry->PowerType == POWER_COMBO_POINTS && (!powerEntry->RequiredAuraSpellID || unit->HasAura(powerEntry->RequiredAuraSpellID));
+ });
+
+ if (itr == spellInfo->PowerCosts.end())
+ return minduration;
+
+ auto consumedItr = std::find_if(powerCosts->begin(), powerCosts->end(),
+ [](SpellPowerCost const& consumed) { return consumed.Power == POWER_COMBO_POINTS; });
+ if (consumedItr == powerCosts->end())
+ return minduration;
+
+ int32 baseComboCost = (*itr)->ManaCost + (*itr)->OptionalCost;
+ if (PowerTypeEntry const* powerTypeEntry = sDB2Manager.GetPowerTypeEntry(POWER_COMBO_POINTS))
+ baseComboCost += int32(CalculatePct(powerTypeEntry->MaxBasePower, (*itr)->PowerCostPct + (*itr)->OptionalCostPct));
- return duration;
+ float durationPerComboPoint = float(maxduration - minduration) / baseComboCost;
+ return minduration + int32(durationPerComboPoint * consumedItr->Amount);
}
int32 WorldObject::ModSpellDuration(SpellInfo const* spellInfo, WorldObject const* target, int32 duration, bool positive, uint32 effectMask) const
diff --git a/src/server/game/Entities/Object/Object.h b/src/server/game/Entities/Object/Object.h
index 629367079a8..b1281a3cff7 100644
--- a/src/server/game/Entities/Object/Object.h
+++ b/src/server/game/Entities/Object/Object.h
@@ -64,6 +64,7 @@ struct FactionTemplateEntry;
struct Loot;
struct PositionFullTerrainStatus;
struct QuaternionData;
+struct SpellPowerCost;
enum ZLiquidStatus : uint32;
namespace WorldPackets
@@ -642,7 +643,7 @@ class TC_GAME_API WorldObject : public Object, public WorldLocation
float GetSpellMinRangeForTarget(Unit const* target, SpellInfo const* spellInfo) const;
double ApplyEffectModifiers(SpellInfo const* spellInfo, uint8 effIndex, double value) const;
- int32 CalcSpellDuration(SpellInfo const* spellInfo) const;
+ int32 CalcSpellDuration(SpellInfo const* spellInfo, std::vector<SpellPowerCost> const* powerCosts) const;
int32 ModSpellDuration(SpellInfo const* spellInfo, WorldObject const* target, int32 duration, bool positive, uint32 effectMask) const;
void ModSpellCastTime(SpellInfo const* spellInfo, int32& castTime, Spell* spell = nullptr) const;
void ModSpellDurationTime(SpellInfo const* spellInfo, int32& durationTime, Spell* spell = nullptr) const;
diff --git a/src/server/game/Spells/Auras/SpellAuraEffects.cpp b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
index d511bc2dfa3..665e6fca4de 100644
--- a/src/server/game/Spells/Auras/SpellAuraEffects.cpp
+++ b/src/server/game/Spells/Auras/SpellAuraEffects.cpp
@@ -750,7 +750,7 @@ Optional<float> AuraEffect::CalculateEstimatedAmount(Unit const* caster, int32 a
float AuraEffect::CalculateEstimatedfTotalPeriodicAmount(Unit* caster, Unit* target, SpellInfo const* spellInfo, SpellEffectInfo const& spellEffectInfo,
float amount, uint8 stack)
{
- int32 maxDuration = Aura::CalcMaxDuration(spellInfo, caster);
+ int32 maxDuration = Aura::CalcMaxDuration(spellInfo, caster, nullptr);
if (maxDuration <= 0)
return 0.0f;
diff --git a/src/server/game/Spells/Auras/SpellAuras.cpp b/src/server/game/Spells/Auras/SpellAuras.cpp
index 59c54cd73df..7021f4a0367 100644
--- a/src/server/game/Spells/Auras/SpellAuras.cpp
+++ b/src/server/game/Spells/Auras/SpellAuras.cpp
@@ -859,10 +859,10 @@ void Aura::Update(uint32 diff, Unit* caster)
int32 Aura::CalcMaxDuration(Unit* caster) const
{
- return Aura::CalcMaxDuration(GetSpellInfo(), caster);
+ return Aura::CalcMaxDuration(GetSpellInfo(), caster, nullptr);
}
-/*static*/ int32 Aura::CalcMaxDuration(SpellInfo const* spellInfo, WorldObject* caster)
+/*static*/ int32 Aura::CalcMaxDuration(SpellInfo const* spellInfo, WorldObject const* caster, std::vector<SpellPowerCost> const* powerCosts)
{
Player* modOwner = nullptr;
int32 maxDuration;
@@ -870,7 +870,7 @@ int32 Aura::CalcMaxDuration(Unit* caster) const
if (caster)
{
modOwner = caster->GetSpellModOwner();
- maxDuration = caster->CalcSpellDuration(spellInfo);
+ maxDuration = caster->CalcSpellDuration(spellInfo, powerCosts);
}
else
maxDuration = spellInfo->GetDuration();
diff --git a/src/server/game/Spells/Auras/SpellAuras.h b/src/server/game/Spells/Auras/SpellAuras.h
index aa9829401e0..b57958d003e 100644
--- a/src/server/game/Spells/Auras/SpellAuras.h
+++ b/src/server/game/Spells/Auras/SpellAuras.h
@@ -168,7 +168,7 @@ class TC_GAME_API Aura
void SetMaxDuration(int32 duration) { m_maxDuration = duration; }
int32 CalcMaxDuration() const { return CalcMaxDuration(GetCaster()); }
int32 CalcMaxDuration(Unit* caster) const;
- static int32 CalcMaxDuration(SpellInfo const* spellInfo, WorldObject* caster);
+ static int32 CalcMaxDuration(SpellInfo const* spellInfo, WorldObject const* caster, std::vector<SpellPowerCost> const* powerCosts);
int32 GetDuration() const { return m_duration; }
void SetDuration(int32 duration, bool withMods = false);
void RefreshDuration(bool withMods = false);
diff --git a/src/server/game/Spells/Spell.cpp b/src/server/game/Spells/Spell.cpp
index 1cbc3817bdd..c4aa677563c 100644
--- a/src/server/game/Spells/Spell.cpp
+++ b/src/server/game/Spells/Spell.cpp
@@ -3164,7 +3164,7 @@ SpellMissInfo Spell::PreprocessSpellHit(Unit* unit, TargetInfo& hitInfo)
}
}
- hitInfo.AuraDuration = Aura::CalcMaxDuration(m_spellInfo, origCaster);
+ hitInfo.AuraDuration = Aura::CalcMaxDuration(m_spellInfo, origCaster, &m_powerCost);
// unit is immune to aura if it was diminished to 0 duration
if (!hitInfo.Positive && !unit->ApplyDiminishingToDuration(m_spellInfo, hitInfo.AuraDuration, origCaster, diminishLevel))
diff --git a/src/server/game/Spells/SpellInfo.cpp b/src/server/game/Spells/SpellInfo.cpp
index 2d92b671ba3..b0cef2841d6 100644
--- a/src/server/game/Spells/SpellInfo.cpp
+++ b/src/server/game/Spells/SpellInfo.cpp
@@ -3959,22 +3959,16 @@ Optional<SpellPowerCost> SpellInfo::CalcPowerCost(SpellPowerEntry const* power,
// Spell drain all exist power on cast (Only paladin lay of Hands)
if (HasAttribute(SPELL_ATTR1_USE_ALL_MANA))
{
+ if (optionalCost)
+ return {};
+
// If power type - health drain all
if (power->PowerType == POWER_HEALTH)
- {
- SpellPowerCost cost;
- cost.Power = POWER_HEALTH;
- cost.Amount = unitCaster->GetHealth();
- return cost;
- }
+ return SpellPowerCost{ .Power = POWER_HEALTH, .Amount = int32(unitCaster->GetHealth()) };
+
// Else drain all power
if (power->PowerType < MAX_POWERS)
- {
- SpellPowerCost cost;
- cost.Power = Powers(power->PowerType);
- cost.Amount = unitCaster->GetPower(cost.Power);
- return cost;
- }
+ return SpellPowerCost{ .Power = Powers(power->PowerType), .Amount = unitCaster->GetPower(Powers(power->PowerType)) };
TC_LOG_ERROR("spells", "SpellInfo::CalcPowerCost: Unknown power type '{}' in spell {}", power->PowerType, Id);
return {};
@@ -4158,10 +4152,7 @@ Optional<SpellPowerCost> SpellInfo::CalcPowerCost(SpellPowerEntry const* power,
if (initiallyNegative != (powerCost < 0))
powerCost = 0;
- SpellPowerCost cost;
- cost.Power = Powers(power->PowerType);
- cost.Amount = powerCost;
- return cost;
+ return SpellPowerCost{ .Power = Powers(power->PowerType), .Amount = powerCost };
}
std::vector<SpellPowerCost> SpellInfo::CalcPowerCost(WorldObject const* caster, SpellSchoolMask schoolMask, Spell* spell) const
@@ -4180,11 +4171,7 @@ std::vector<SpellPowerCost> SpellInfo::CalcPowerCost(WorldObject const* caster,
if (itr != costs.end())
return *itr;
- SpellPowerCost cost;
- cost.Power = powerType;
- cost.Amount = 0;
- costs.push_back(cost);
- return costs.back();
+ return costs.emplace_back<SpellPowerCost>({ .Power = powerType, .Amount = 0 });
};
for (SpellPowerEntry const* power : PowerCosts)