[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:
zergtmn 2011-03-30 23:29:01 +06:00
parent 5833d74963
commit 4687fa8cb4
19 changed files with 388 additions and 379 deletions

View file

@ -1243,7 +1243,7 @@ void Pet::_LoadAuras(uint32 timediff)
{
RemoveAllAuras();
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,item_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,maxduration0,maxduration1,maxduration2,remaintime0,remaintime1,remaintime2,effIndexMask FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,item_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,periodictime0,periodictime1,periodictime2,maxduration,remaintime,effIndexMask FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber());
if(result)
{
@ -1255,16 +1255,18 @@ void Pet::_LoadAuras(uint32 timediff)
uint32 spellid = fields[2].GetUInt32();
uint32 stackcount = fields[3].GetUInt32();
uint32 remaincharges = fields[4].GetUInt32();
int32 damage[MAX_EFFECT_INDEX];
int32 maxduration[MAX_EFFECT_INDEX];
int32 remaintime[MAX_EFFECT_INDEX];
int32 damage[MAX_EFFECT_INDEX];
uint32 periodicTime[MAX_EFFECT_INDEX];
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
damage[i] = fields[i+5].GetInt32();
maxduration[i] = fields[i+8].GetInt32();
remaintime[i] = fields[i+11].GetInt32();
periodicTime[i] = fields[i+8].GetUInt32();
}
uint32 effIndexMask = fields[14].GetUInt32();
int32 maxduration = fields[11].GetInt32();
int32 remaintime = fields[12].GetInt32();
uint32 effIndexMask = fields[13].GetUInt32();
SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid);
if (!spellproto)
@ -1277,6 +1279,14 @@ void Pet::_LoadAuras(uint32 timediff)
if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
continue;
if (remaintime != -1 && !IsPositiveSpell(spellproto))
{
if (remaintime/IN_MILLISECONDS <= int32(timediff))
continue;
remaintime -= timediff*IN_MILLISECONDS;
}
// prevent wrong values of remaincharges
uint32 procCharges = spellproto->procCharges;
if (procCharges)
@ -1294,34 +1304,24 @@ void Pet::_LoadAuras(uint32 timediff)
else if (!stackcount)
stackcount = 1;
SpellAuraHolder *holder = CreateSpellAuraHolder(spellproto, this, NULL);
holder->SetLoadedState(caster_guid, ObjectGuid(HIGHGUID_ITEM, item_lowguid), stackcount, remaincharges, maxduration, remaintime);
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if ((effIndexMask & (1 << i)) == 0)
continue;
if (remaintime[i] != -1 && !IsPositiveEffect(spellproto, SpellEffectIndex(i)))
{
if (remaintime[i]/IN_MILLISECONDS <= int32(timediff))
continue;
remaintime[i] -= timediff*IN_MILLISECONDS;
}
Aura* aura = CreateAura(spellproto, SpellEffectIndex(i), NULL, holder, this);
if (!damage[i])
damage[i] = aura->GetModifier()->m_amount;
aura->SetLoadedState(damage[i], maxduration[i], remaintime[i]);
aura->SetLoadedState(damage[i], periodicTime[i]);
holder->AddAura(aura, SpellEffectIndex(i));
}
if (!holder->IsEmptyHolder())
{
holder->SetLoadedState(caster_guid, ObjectGuid(HIGHGUID_ITEM, item_lowguid), stackcount, remaincharges);
AddSpellAuraHolder(holder);
}
else
delete holder;
}
@ -1344,6 +1344,10 @@ void Pet::_SaveAuras()
if (auraHolders.empty())
return;
stmt = CharacterDatabase.CreateStatement(insAuras, "INSERT INTO pet_aura (guid, caster_guid, item_guid, spell, stackcount, remaincharges, "
"basepoints0, basepoints1, basepoints2, periodictime0, periodictime1, periodictime2, maxduration, remaintime, effIndexMask) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
for(SpellAuraHolderMap::const_iterator itr = auraHolders.begin(); itr != auraHolders.end(); ++itr)
{
SpellAuraHolder *holder = itr->second;
@ -1365,16 +1369,14 @@ void Pet::_SaveAuras()
//do not save single target holders (unless they were cast by the player)
if (save && !holder->IsPassive() && !IsChanneledSpell(holder->GetSpellProto()) && (holder->GetCasterGUID() == GetGUID() || !holder->IsSingleTarget()))
{
int32 damage[MAX_EFFECT_INDEX];
int32 remaintime[MAX_EFFECT_INDEX];
int32 maxduration[MAX_EFFECT_INDEX];
int32 damage[MAX_EFFECT_INDEX];
uint32 periodicTime[MAX_EFFECT_INDEX];
uint32 effIndexMask = 0;
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
damage[i] = 0;
remaintime[i] = 0;
maxduration[i] = 0;
periodicTime[i] = 0;
if (Aura *aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i)))
{
@ -1383,8 +1385,7 @@ void Pet::_SaveAuras()
continue;
damage[i] = aur->GetModifier()->m_amount;
remaintime[i] = aur->GetAuraDuration();
maxduration[i] = aur->GetAuraMaxDuration();
periodicTime[i] = aur->GetModifier()->periodictime;
effIndexMask |= (1 << i);
}
}
@ -1392,9 +1393,6 @@ void Pet::_SaveAuras()
if (!effIndexMask)
continue;
stmt = CharacterDatabase.CreateStatement(insAuras, "INSERT INTO pet_aura (guid, caster_guid, item_guid, spell, stackcount, remaincharges, basepoints0, basepoints1, basepoints2, maxduration0, maxduration1, maxduration2, remaintime0, remaintime1, remaintime2, effIndexMask) "
"VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)");
stmt.addUInt32(m_charmInfo->GetPetNumber());
stmt.addUInt64(holder->GetCasterGuid().GetRawValue());
stmt.addUInt32(holder->GetCastItemGuid().GetCounter());
@ -1402,15 +1400,14 @@ void Pet::_SaveAuras()
stmt.addUInt32(holder->GetStackAmount());
stmt.addUInt8(holder->GetAuraCharges());
for (int i = EFFECT_INDEX_0; i <= EFFECT_INDEX_2; ++i )
for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i)
stmt.addInt32(damage[i]);
for (int i = EFFECT_INDEX_0; i <= EFFECT_INDEX_2; ++i )
stmt.addInt32(maxduration[i]);
for (int i = EFFECT_INDEX_0; i <= EFFECT_INDEX_2; ++i )
stmt.addInt32(remaintime[i]);
for (uint32 i = 0; i < MAX_EFFECT_INDEX; ++i)
stmt.addUInt32(periodicTime[i]);
stmt.addInt32(holder->GetAuraMaxDuration());
stmt.addInt32(holder->GetAuraDuration());
stmt.addUInt32(effIndexMask);
stmt.Execute();
}