mirror of
https://github.com/mangosfour/server.git
synced 2025-12-18 01:37:01 +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
|
|
@ -282,9 +282,9 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
&Aura::HandleNoImmediateEffect, //229 SPELL_AURA_MOD_AOE_DAMAGE_AVOIDANCE implemented in Unit::SpellDamageBonusTaken
|
||||
&Aura::HandleAuraModIncreaseMaxHealth, //230 Commanding Shout
|
||||
&Aura::HandleNoImmediateEffect, //231 SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE
|
||||
&Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateSpellDuration
|
||||
&Aura::HandleNoImmediateEffect, //232 SPELL_AURA_MECHANIC_DURATION_MOD implement in Unit::CalculateAuraDuration
|
||||
&Aura::HandleNULL, //233 set model id to the one of the creature with id m_modifier.m_miscvalue
|
||||
&Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateSpellDuration
|
||||
&Aura::HandleNoImmediateEffect, //234 SPELL_AURA_MECHANIC_DURATION_MOD_NOT_STACK implement in Unit::CalculateAuraDuration
|
||||
&Aura::HandleAuraModDispelResist, //235 SPELL_AURA_MOD_DISPEL_RESIST implement in Unit::MagicSpellHitResult
|
||||
&Aura::HandleAuraControlVehicle, //236 SPELL_AURA_CONTROL_VEHICLE
|
||||
&Aura::HandleModSpellDamagePercentFromAttackPower, //237 SPELL_AURA_MOD_SPELL_DAMAGE_OF_ATTACK_POWER implemented in Unit::SpellBaseDamageBonusDone
|
||||
|
|
@ -295,8 +295,8 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
&Aura::HandleUnused, //242 SPELL_AURA_MOD_SPELL_DAMAGE_FROM_HEALING (only 2 test spels in 3.2.2a)
|
||||
&Aura::HandleNULL, //243 faction reaction override spells
|
||||
&Aura::HandleComprehendLanguage, //244 SPELL_AURA_COMPREHEND_LANGUAGE
|
||||
&Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS implemented in Unit::CalculateSpellDuration
|
||||
&Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL implemented in Unit::CalculateSpellDuration
|
||||
&Aura::HandleNoImmediateEffect, //245 SPELL_AURA_MOD_DURATION_OF_MAGIC_EFFECTS implemented in Unit::CalculateAuraDuration
|
||||
&Aura::HandleNoImmediateEffect, //246 SPELL_AURA_MOD_DURATION_OF_EFFECTS_BY_DISPEL implemented in Unit::CalculateAuraDuration
|
||||
&Aura::HandleNULL, //247 target to become a clone of the caster
|
||||
&Aura::HandleNoImmediateEffect, //248 SPELL_AURA_MOD_COMBAT_RESULT_CHANCE implemented in Unit::RollMeleeOutcomeAgainst
|
||||
&Aura::HandleAuraConvertRune, //249 SPELL_AURA_CONVERT_RUNE
|
||||
|
|
@ -372,33 +372,24 @@ pAuraHandler AuraHandler[TOTAL_AURAS]=
|
|||
static AuraType const frozenAuraTypes[] = { SPELL_AURA_MOD_ROOT, SPELL_AURA_MOD_STUN, SPELL_AURA_NONE };
|
||||
|
||||
Aura::Aura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster, Item* castItem) :
|
||||
m_spellmod(NULL),
|
||||
m_timeCla(1000), m_periodicTimer(0), m_periodicTick(0), m_removeMode(AURA_REMOVE_BY_DEFAULT),
|
||||
m_spellmod(NULL), m_periodicTimer(0), m_periodicTick(0), m_removeMode(AURA_REMOVE_BY_DEFAULT),
|
||||
m_effIndex(eff), m_positive(false), m_isPeriodic(false), m_isAreaAura(false),
|
||||
m_isPersistent(false), m_in_use(0), m_spellAuraHolder(holder)
|
||||
{
|
||||
MANGOS_ASSERT(target);
|
||||
|
||||
MANGOS_ASSERT(spellproto && spellproto == sSpellStore.LookupEntry( spellproto->Id ) && "`info` must be pointer to sSpellStore element");
|
||||
|
||||
m_currentBasePoints = currentBasePoints ? *currentBasePoints : spellproto->CalculateSimpleValue(eff);
|
||||
|
||||
bool isPassive = IsPassiveSpell(GetSpellProto());
|
||||
bool isPermanent = false;
|
||||
m_positive = IsPositiveEffect(spellproto, m_effIndex);
|
||||
|
||||
m_applyTime = time(NULL);
|
||||
|
||||
int32 damage;
|
||||
if (!caster)
|
||||
{
|
||||
damage = m_currentBasePoints;
|
||||
m_maxduration = target->CalculateSpellDuration(spellproto, m_effIndex, target);
|
||||
}
|
||||
else
|
||||
{
|
||||
damage = caster->CalculateSpellDamage(target, spellproto, m_effIndex, &m_currentBasePoints);
|
||||
m_maxduration = caster->CalculateSpellDuration(spellproto, m_effIndex, target);
|
||||
damage = caster->CalculateSpellDamage(target, spellproto, m_effIndex, &m_currentBasePoints);
|
||||
|
||||
if (!damage && castItem && castItem->GetItemSuffixFactor())
|
||||
{
|
||||
|
|
@ -427,32 +418,19 @@ m_isPersistent(false), m_in_use(0), m_spellAuraHolder(holder)
|
|||
}
|
||||
}
|
||||
|
||||
if (m_maxduration == -1 || (isPassive && spellproto->DurationIndex == 0))
|
||||
isPermanent = true;
|
||||
|
||||
Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
|
||||
|
||||
if (!isPermanent && modOwner)
|
||||
{
|
||||
modOwner->ApplySpellMod(spellproto->Id, SPELLMOD_DURATION, m_maxduration);
|
||||
// Get zero duration aura after - need set m_maxduration > 0 for apply/remove aura work
|
||||
if (m_maxduration<=0)
|
||||
m_maxduration = 1;
|
||||
}
|
||||
|
||||
m_duration = m_maxduration;
|
||||
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Aura: construct Spellid : %u, Aura : %u Duration : %d Target : %d Damage : %d", spellproto->Id, spellproto->EffectApplyAuraName[eff], m_maxduration, spellproto->EffectImplicitTargetA[eff],damage);
|
||||
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Aura: construct Spellid : %u, Aura : %u Target : %d Damage : %d", spellproto->Id, spellproto->EffectApplyAuraName[eff], spellproto->EffectImplicitTargetA[eff], damage);
|
||||
|
||||
SetModifier(AuraType(spellproto->EffectApplyAuraName[eff]), damage, spellproto->EffectAmplitude[eff], spellproto->EffectMiscValue[eff]);
|
||||
|
||||
Player* modOwner = caster ? caster->GetSpellModOwner() : NULL;
|
||||
|
||||
// Apply periodic time mod
|
||||
if(modOwner && m_modifier.periodictime)
|
||||
if (modOwner && m_modifier.periodictime)
|
||||
modOwner->ApplySpellMod(spellproto->Id, SPELLMOD_ACTIVATION_TIME, m_modifier.periodictime);
|
||||
|
||||
// Start periodic on next tick or at aura apply
|
||||
if (!(spellproto->AttributesEx5 & SPELL_ATTR_EX5_START_PERIODIC_AT_APPLY))
|
||||
m_periodicTimer += m_modifier.periodictime;
|
||||
m_periodicTimer = m_modifier.periodictime;
|
||||
}
|
||||
|
||||
Aura::~Aura()
|
||||
|
|
@ -569,34 +547,7 @@ void Aura::SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue)
|
|||
|
||||
void Aura::Update(uint32 diff)
|
||||
{
|
||||
if (m_duration > 0)
|
||||
{
|
||||
m_duration -= diff;
|
||||
if (m_duration < 0)
|
||||
m_duration = 0;
|
||||
m_timeCla -= diff;
|
||||
|
||||
// GetEffIndex()==0 prevent double/triple apply manaPerSecond/manaPerSecondPerLevel to same spell with many auras
|
||||
// all spells with manaPerSecond/manaPerSecondPerLevel have aura in effect 0
|
||||
if (GetEffIndex() == EFFECT_INDEX_0 && m_timeCla <= 0)
|
||||
{
|
||||
if(Unit* caster = GetCaster())
|
||||
{
|
||||
Powers powertype = Powers(GetSpellProto()->powerType);
|
||||
int32 manaPerSecond = GetSpellProto()->manaPerSecond + GetSpellProto()->manaPerSecondPerLevel * caster->getLevel();
|
||||
m_timeCla = 1*IN_MILLISECONDS;
|
||||
if (manaPerSecond)
|
||||
{
|
||||
if(powertype==POWER_HEALTH)
|
||||
caster->ModifyHealth(-manaPerSecond);
|
||||
else
|
||||
caster->ModifyPower(powertype,-manaPerSecond);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(m_isPeriodic && (m_duration >= 0 || GetHolder()->IsPassive() || GetHolder()->IsPermanent()))
|
||||
if (m_isPeriodic)
|
||||
{
|
||||
m_periodicTimer -= diff;
|
||||
if(m_periodicTimer <= 0) // tick also at m_periodicTimer==0 to prevent lost last tick in case max m_duration == (max m_periodicTimer)*N
|
||||
|
|
@ -776,8 +727,9 @@ void AreaAura::Update(uint32 diff)
|
|||
addedToExisting = false;
|
||||
}
|
||||
|
||||
holder->SetAuraDuration(GetAuraDuration());
|
||||
|
||||
AreaAura *aur = new AreaAura(actualSpellInfo, m_effIndex, &actualBasePoints, holder, (*tIter), caster, NULL);
|
||||
aur->SetAuraDuration(GetAuraDuration());
|
||||
holder->AddAura(aur, m_effIndex);
|
||||
|
||||
if (addedToExisting)
|
||||
|
|
@ -1991,7 +1943,7 @@ void Aura::HandleAuraDummy(bool apply, bool Real)
|
|||
// max duration is 2 minutes, but expected to be random duration
|
||||
// real time randomness is unclear, using max 30 seconds here
|
||||
// see further down for expire of this aura
|
||||
SetAuraDuration(rand()%30*IN_MILLISECONDS);
|
||||
GetHolder()->SetAuraDuration(urand(1, 30)*IN_MILLISECONDS);
|
||||
return;
|
||||
}
|
||||
// Gender spells
|
||||
|
|
@ -4371,10 +4323,10 @@ void Aura::HandleModStealth(bool apply, bool Real)
|
|||
// Overkill
|
||||
else if ((*i)->GetId() == 58426 && GetSpellProto()->SpellFamilyFlags & UI64LIT(0x0000000000400000))
|
||||
{
|
||||
if (Aura* aura = target->GetAura(58427, EFFECT_INDEX_0))
|
||||
if (SpellAuraHolder* holder = target->GetSpellAuraHolder(58427))
|
||||
{
|
||||
aura->SetAuraMaxDuration(20*IN_MILLISECONDS);
|
||||
aura->GetHolder()->RefreshHolder();
|
||||
holder->SetAuraMaxDuration(20*IN_MILLISECONDS);
|
||||
holder->RefreshHolder();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -8174,20 +8126,6 @@ void Aura::HandleAuraModAllCritChance(bool apply, bool Real)
|
|||
((Player*)target)->UpdateAllSpellCritChances();
|
||||
}
|
||||
|
||||
void Aura::SetAuraMaxDuration(int32 duration)
|
||||
{
|
||||
m_maxduration = duration;
|
||||
|
||||
// possible overwrite persistent state
|
||||
if (duration > 0)
|
||||
{
|
||||
if (!(GetHolder()->IsPassive() && GetSpellProto()->DurationIndex == 0))
|
||||
GetHolder()->SetPermanent(false);
|
||||
|
||||
GetHolder()->SetAuraFlags(GetHolder()->GetAuraFlags() | AFLAG_DURATION);
|
||||
}
|
||||
}
|
||||
|
||||
bool Aura::IsLastAuraOnHolder()
|
||||
{
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
|
|
@ -8203,9 +8141,9 @@ bool Aura::HasMechanic(uint32 mechanic) const
|
|||
}
|
||||
|
||||
SpellAuraHolder::SpellAuraHolder(SpellEntry const* spellproto, Unit *target, WorldObject *caster, Item *castItem) :
|
||||
m_target(target), m_castItemGuid(castItem ? castItem->GetObjectGuid() : ObjectGuid()),
|
||||
m_spellProto(spellproto), m_target(target), m_castItemGuid(castItem ? castItem->GetObjectGuid() : ObjectGuid()),
|
||||
m_auraSlot(MAX_AURAS), m_auraFlags(AFLAG_NONE), m_auraLevel(1), m_procCharges(0),
|
||||
m_stackAmount(1), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE),
|
||||
m_stackAmount(1), m_removeMode(AURA_REMOVE_BY_DEFAULT), m_AuraDRGroup(DIMINISHING_NONE), m_timeCla(1000),
|
||||
m_permanent(false), m_isRemovedOnShapeLost(true), m_deleted(false), m_in_use(0)
|
||||
{
|
||||
MANGOS_ASSERT(target);
|
||||
|
|
@ -8216,29 +8154,33 @@ m_permanent(false), m_isRemovedOnShapeLost(true), m_deleted(false), m_in_use(0)
|
|||
else
|
||||
{
|
||||
// remove this assert when not unit casters will be supported
|
||||
MANGOS_ASSERT(caster->GetObjectGuid().IsUnit())
|
||||
MANGOS_ASSERT(caster->isType(TYPEMASK_UNIT))
|
||||
m_casterGuid = caster->GetObjectGuid();
|
||||
}
|
||||
|
||||
m_applyTime = time(NULL);
|
||||
m_spellProto = spellproto;
|
||||
m_isPassive = IsPassiveSpell(GetId());
|
||||
m_isDeathPersist = IsDeathPersistentSpell(m_spellProto);
|
||||
m_applyTime = time(NULL);
|
||||
m_isPassive = IsPassiveSpell(spellproto);
|
||||
m_isDeathPersist = IsDeathPersistentSpell(spellproto);
|
||||
m_isSingleTarget = IsSingleTargetSpell(spellproto);
|
||||
|
||||
if (GetSpellMaxDuration(m_spellProto) == -1 || (m_isPassive && m_spellProto->DurationIndex == 0))
|
||||
m_permanent = true;
|
||||
m_procCharges = spellproto->procCharges;
|
||||
|
||||
m_isRemovedOnShapeLost = (GetCasterGuid() == m_target->GetObjectGuid() &&
|
||||
m_spellProto->Stances &&
|
||||
!(m_spellProto->AttributesEx2 & SPELL_ATTR_EX2_NOT_NEED_SHAPESHIFT) &&
|
||||
!(m_spellProto->Attributes & SPELL_ATTR_NOT_SHAPESHIFT));
|
||||
|
||||
Player* modOwner = caster && caster->GetObjectGuid().IsUnit() ? ((Unit*)caster)->GetSpellModOwner() : NULL;
|
||||
Unit* unitCaster = caster && caster->isType(TYPEMASK_UNIT) ? (Unit*)caster : NULL;
|
||||
|
||||
m_procCharges = m_spellProto->procCharges;
|
||||
if(modOwner)
|
||||
modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
|
||||
m_duration = m_maxDuration = CalculateSpellDuration(spellproto, unitCaster);
|
||||
|
||||
if (m_maxDuration == -1 || (m_isPassive && spellproto->DurationIndex == 0))
|
||||
m_permanent = true;
|
||||
|
||||
if (unitCaster)
|
||||
{
|
||||
if (Player* modOwner = unitCaster->GetSpellModOwner())
|
||||
modOwner->ApplySpellMod(GetId(), SPELLMOD_CHARGES, m_procCharges);
|
||||
}
|
||||
|
||||
// some custom stack values at aura holder create
|
||||
switch (m_spellProto->Id)
|
||||
|
|
@ -8697,23 +8639,8 @@ void SpellAuraHolder::BuildUpdatePacket(WorldPacket& data) const
|
|||
|
||||
if(auraFlags & AFLAG_DURATION)
|
||||
{
|
||||
// take highest - to display icon even if stun fades
|
||||
uint32 max_duration = 0;
|
||||
uint32 duration = 0;
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
{
|
||||
if (Aura *aura = m_auras[i])
|
||||
{
|
||||
if (uint32(aura->GetAuraMaxDuration()) > max_duration)
|
||||
{
|
||||
max_duration = aura->GetAuraMaxDuration();
|
||||
duration = aura->GetAuraDuration();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
data << uint32(max_duration);
|
||||
data << uint32(duration);
|
||||
data << uint32(GetAuraMaxDuration());
|
||||
data << uint32(GetAuraDuration());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -9403,6 +9330,33 @@ SpellAuraHolder::~SpellAuraHolder()
|
|||
|
||||
void SpellAuraHolder::Update(uint32 diff)
|
||||
{
|
||||
if (m_duration > 0)
|
||||
{
|
||||
m_duration -= diff;
|
||||
if (m_duration < 0)
|
||||
m_duration = 0;
|
||||
|
||||
m_timeCla -= diff;
|
||||
|
||||
if (m_timeCla <= 0)
|
||||
{
|
||||
if (Unit* caster = GetCaster())
|
||||
{
|
||||
Powers powertype = Powers(GetSpellProto()->powerType);
|
||||
int32 manaPerSecond = GetSpellProto()->manaPerSecond + GetSpellProto()->manaPerSecondPerLevel * caster->getLevel();
|
||||
m_timeCla = 1*IN_MILLISECONDS;
|
||||
|
||||
if (manaPerSecond)
|
||||
{
|
||||
if (powertype == POWER_HEALTH)
|
||||
caster->ModifyHealth(-manaPerSecond);
|
||||
else
|
||||
caster->ModifyPower(powertype, -manaPerSecond);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
if (Aura *aura = m_auras[i])
|
||||
aura->UpdateAura(diff);
|
||||
|
|
@ -9437,13 +9391,26 @@ void SpellAuraHolder::Update(uint32 diff)
|
|||
|
||||
void SpellAuraHolder::RefreshHolder()
|
||||
{
|
||||
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
|
||||
if (Aura *aura = m_auras[i])
|
||||
aura->SetAuraDuration(aura->GetAuraMaxDuration());
|
||||
|
||||
SetAuraDuration(GetAuraMaxDuration());
|
||||
SendAuraUpdate(false);
|
||||
}
|
||||
|
||||
void SpellAuraHolder::SetAuraMaxDuration(int32 duration)
|
||||
{
|
||||
m_maxDuration = duration;
|
||||
|
||||
// possible overwrite persistent state
|
||||
if (duration > 0)
|
||||
{
|
||||
if (!(IsPassive() && GetSpellProto()->DurationIndex == 0))
|
||||
SetPermanent(false);
|
||||
|
||||
SetAuraFlags(GetAuraFlags() | AFLAG_DURATION);
|
||||
}
|
||||
else
|
||||
SetAuraFlags(GetAuraFlags() & ~AFLAG_DURATION);
|
||||
}
|
||||
|
||||
bool SpellAuraHolder::HasMechanic(uint32 mechanic) const
|
||||
{
|
||||
if (mechanic == m_spellProto->Mechanic)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue