mirror of
https://github.com/mangosfour/server.git
synced 2025-12-13 04:37:00 +00:00
[11299] Handle aura durations in SpellAuraHolder
- Unit::CalculateSpellDuration split into two functions
- CalculateSpellDuration taking into account combo points and caster-side spell mods
- Unit::CalculateAuraDuration taking into account target-side spell mods
- Diminishing is now applied before duration reduction mods
- Implement saving per-effect periodic timers to DB (required for auras affected by haste)
This commit is contained in:
parent
5833d74963
commit
4687fa8cb4
19 changed files with 388 additions and 379 deletions
|
|
@ -3489,31 +3489,11 @@ void Unit::_UpdateSpells( uint32 time )
|
|||
for (SpellAuraHolderMap::iterator iter = m_spellAuraHolders.begin(); iter != m_spellAuraHolders.end();)
|
||||
{
|
||||
SpellAuraHolder *holder = iter->second;
|
||||
if (holder)
|
||||
{
|
||||
if (!(holder->IsPermanent() || holder->IsPassive()) )
|
||||
{
|
||||
bool removedAura = false;
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{
|
||||
if (Aura *aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i)))
|
||||
{
|
||||
if (!aura->GetAuraDuration())
|
||||
{
|
||||
RemoveSingleAuraFromSpellAuraHolder(holder, aura->GetEffIndex(), AURA_REMOVE_BY_EXPIRE);
|
||||
removedAura = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (!removedAura)
|
||||
++iter;
|
||||
else
|
||||
iter = m_spellAuraHolders.begin();
|
||||
}
|
||||
else
|
||||
++iter;
|
||||
if (!(holder->IsPermanent() || holder->IsPassive()) && holder->GetAuraDuration() == 0)
|
||||
{
|
||||
RemoveSpellAuraHolder(holder, AURA_REMOVE_BY_EXPIRE);
|
||||
iter = m_spellAuraHolders.begin();
|
||||
}
|
||||
else
|
||||
++iter;
|
||||
|
|
@ -4505,6 +4485,14 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit
|
|||
SpellEntry const* spellProto = sSpellStore.LookupEntry(spellId);
|
||||
SpellAuraHolder *new_holder = CreateSpellAuraHolder(spellProto, stealer, this);
|
||||
|
||||
// set its duration and maximum duration
|
||||
// max duration 2 minutes (in msecs)
|
||||
int32 dur = holder->GetAuraDuration();
|
||||
int32 max_dur = 2*MINUTE*IN_MILLISECONDS;
|
||||
int32 new_max_dur = max_dur > dur ? dur : max_dur;
|
||||
new_holder->SetAuraMaxDuration(new_max_dur);
|
||||
new_holder->SetAuraDuration(new_max_dur);
|
||||
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{
|
||||
Aura *aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i));
|
||||
|
|
@ -4517,14 +4505,6 @@ void Unit::RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit
|
|||
// some different constructors
|
||||
Aura * new_aur = CreateAura(aur->GetSpellProto(), aur->GetEffIndex(), &basePoints, new_holder, stealer, this);
|
||||
|
||||
// set its duration and maximum duration
|
||||
// max duration 2 minutes (in msecs)
|
||||
int32 dur = aur->GetAuraDuration();
|
||||
int32 max_dur = 2*MINUTE*IN_MILLISECONDS;
|
||||
int32 new_max_dur = max_dur > dur ? dur : max_dur;
|
||||
new_aur->SetAuraMaxDuration( new_max_dur );
|
||||
new_aur->SetAuraDuration( new_max_dur );
|
||||
|
||||
// set periodic to do at least one tick (for case when original aura has been at last tick preparing)
|
||||
int32 periodic = aur->GetModifier()->periodictime;
|
||||
new_aur->GetModifier()->periodictime = periodic < new_max_dur ? periodic : new_max_dur;
|
||||
|
|
@ -4885,22 +4865,19 @@ void Unit::DelaySpellAuraHolder(uint32 spellId, int32 delaytime, uint64 casterGU
|
|||
SpellAuraHolderBounds bounds = GetSpellAuraHolderBounds(spellId);
|
||||
for (SpellAuraHolderMap::iterator iter = bounds.first; iter != bounds.second; ++iter)
|
||||
{
|
||||
if (casterGUID != iter->second->GetCasterGUID())
|
||||
SpellAuraHolder* holder = iter->second;
|
||||
|
||||
if (casterGUID != holder->GetCasterGUID())
|
||||
continue;
|
||||
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{
|
||||
if (Aura *aur = iter->second->GetAuraByEffectIndex(SpellEffectIndex(i)))
|
||||
{
|
||||
if (aur->GetAuraDuration() < delaytime)
|
||||
aur->SetAuraDuration(0);
|
||||
else
|
||||
aur->SetAuraDuration(aur->GetAuraDuration() - delaytime);
|
||||
if (holder->GetAuraDuration() < delaytime)
|
||||
holder->SetAuraDuration(0);
|
||||
else
|
||||
holder->SetAuraDuration(holder->GetAuraDuration() - delaytime);
|
||||
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell %u, EffectIndex %u partially interrupted on unit %u, new duration: %u ms",spellId, i, GetGUIDLow(), aur->GetAuraDuration());
|
||||
}
|
||||
}
|
||||
iter->second->SendAuraUpdate(false);
|
||||
holder->SendAuraUpdate(false);
|
||||
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell %u partially interrupted on %s, new duration: %u ms", spellId, GetObjectGuid().GetString().c_str(), holder->GetAuraDuration());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -8729,50 +8706,45 @@ int32 Unit::CalculateSpellDamage(Unit const* target, SpellEntry const* spellProt
|
|||
return value;
|
||||
}
|
||||
|
||||
int32 Unit::CalculateSpellDuration(SpellEntry const* spellProto, SpellEffectIndex effect_index, Unit const* target)
|
||||
int32 Unit::CalculateAuraDuration(SpellEntry const* spellProto, uint32 effectMask, int32 duration, Unit const* caster)
|
||||
{
|
||||
Player* unitPlayer = (GetTypeId() == TYPEID_PLAYER) ? (Player*)this : NULL;
|
||||
if (duration <= 0)
|
||||
return duration;
|
||||
|
||||
uint8 comboPoints = unitPlayer ? unitPlayer->GetComboPoints() : 0;
|
||||
int32 mechanicMod = 0;
|
||||
uint32 mechanicMask = GetSpellMechanicMask(spellProto, effectMask);
|
||||
|
||||
int32 minduration = GetSpellDuration(spellProto);
|
||||
int32 maxduration = GetSpellMaxDuration(spellProto);
|
||||
|
||||
int32 duration;
|
||||
|
||||
if( minduration != -1 && minduration != maxduration )
|
||||
duration = minduration + int32((maxduration - minduration) * comboPoints / 5);
|
||||
else
|
||||
duration = minduration;
|
||||
|
||||
if (duration > 0)
|
||||
for(int32 mechanic = MECHANIC_CHARM; mechanic <= MECHANIC_ENRAGED; ++mechanic)
|
||||
{
|
||||
int32 mechanic = GetEffectMechanic(spellProto, effect_index);
|
||||
// Find total mod value (negative bonus)
|
||||
int32 durationMod_always = target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic);
|
||||
// Modify from SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL aura for negative effects (stack always ?)
|
||||
if (!IsPositiveEffect(spellProto, effect_index))
|
||||
durationMod_always+=target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL, spellProto->Dispel);
|
||||
// Find max mod (negative bonus)
|
||||
int32 durationMod_not_stack = target->GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic);
|
||||
if (!(mechanicMask & (1 << (mechanic-1))))
|
||||
continue;
|
||||
|
||||
if (!IsPositiveSpell(spellProto->Id))
|
||||
durationMod_always += target->GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS, spellProto->DmgClass);
|
||||
int32 stackingMod = GetTotalAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD, mechanic);
|
||||
int32 nonStackingMod = GetMaxNegativeAuraModifierByMiscValue(SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK, mechanic);
|
||||
|
||||
int32 durationMod = 0;
|
||||
// Select strongest negative mod
|
||||
if (durationMod_always > durationMod_not_stack)
|
||||
durationMod = durationMod_not_stack;
|
||||
else
|
||||
durationMod = durationMod_always;
|
||||
|
||||
if (durationMod != 0)
|
||||
duration = int32(int64(duration) * (100+durationMod) /100);
|
||||
|
||||
if (duration < 0) duration = 0;
|
||||
mechanicMod = std::min(mechanicMod, std::min(stackingMod, nonStackingMod));
|
||||
}
|
||||
|
||||
if (duration > 0 && unitPlayer && target == this)
|
||||
int32 dispelMod = 0;
|
||||
int32 dmgClassMod = 0;
|
||||
|
||||
if (!IsPositiveSpell(spellProto))
|
||||
{
|
||||
dispelMod = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL, spellProto->Dispel);
|
||||
dmgClassMod = GetTotalAuraModifierByMiscValue(SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS, spellProto->DmgClass);
|
||||
}
|
||||
|
||||
int32 durationMod = std::min(mechanicMod, std::min(dispelMod, dmgClassMod));
|
||||
|
||||
if (durationMod != 0)
|
||||
{
|
||||
duration = int32(int64(duration) * (100+durationMod) / 100);
|
||||
|
||||
if (duration < 0)
|
||||
duration = 0;
|
||||
}
|
||||
|
||||
if (caster == this)
|
||||
{
|
||||
switch(spellProto->SpellFamilyName)
|
||||
{
|
||||
|
|
@ -9838,7 +9810,7 @@ SpellSchoolMask Unit::GetMeleeDamageSchoolMask() const
|
|||
return SPELL_SCHOOL_MASK_NORMAL;
|
||||
}
|
||||
|
||||
Player* Unit::GetSpellModOwner()
|
||||
Player* Unit::GetSpellModOwner() const
|
||||
{
|
||||
if(GetTypeId()==TYPEID_PLAYER)
|
||||
return (Player*)this;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue