[10156] Add shared object for auras of same spell and move spell proc code to its own file, also spread procs by auras and effect indexes.

This commit is contained in:
Laise 2010-07-07 19:07:53 +03:00
parent abe6776358
commit a32b3063a2
32 changed files with 7507 additions and 6076 deletions

View file

@ -4505,13 +4505,13 @@ void Player::ResurrectPlayer(float restore_percent, bool applySickness)
{
int32 delta = (int32(getLevel()) - startLevel + 1)*MINUTE;
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
if (SpellAuraHolder* holder = GetSpellAuraHolder(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS))
{
if(Aura* Aur = GetAura(SPELL_ID_PASSIVE_RESURRECTION_SICKNESS,SpellEffectIndex(i)))
{
Aur->SetAuraDuration(delta*IN_MILLISECONDS);
Aur->SendAuraUpdate(false);
}
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
if(Aura* Aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i)))
Aur->SetAuraDuration(delta*IN_MILLISECONDS);
holder->SendAuraUpdate(false);
}
}
}
@ -6811,8 +6811,8 @@ void Player::DuelComplete(DuelCompleteType type)
/* remove auras */
std::vector<uint32> auras2remove;
AuraMap const& vAuras = duel->opponent->GetAuras();
for (AuraMap::const_iterator i = vAuras.begin(); i != vAuras.end(); ++i)
SpellAuraHolderMap const& vAuras = duel->opponent->GetSpellAuraHolderMap();
for (SpellAuraHolderMap::const_iterator i = vAuras.begin(); i != vAuras.end(); ++i)
{
if (!i->second->IsPositive() && i->second->GetCasterGUID() == GetGUID() && i->second->GetAuraApplyTime() >= duel->startTime)
auras2remove.push_back(i->second->GetId());
@ -6822,8 +6822,8 @@ void Player::DuelComplete(DuelCompleteType type)
duel->opponent->RemoveAurasDueToSpell(auras2remove[i]);
auras2remove.clear();
AuraMap const& auras = GetAuras();
for (AuraMap::const_iterator i = auras.begin(); i != auras.end(); ++i)
SpellAuraHolderMap const& auras = GetSpellAuraHolderMap();
for (SpellAuraHolderMap::const_iterator i = auras.begin(); i != auras.end(); ++i)
{
if (!i->second->IsPositive() && i->second->GetCasterGUID() == duel->opponent->GetGUID() && i->second->GetAuraApplyTime() >= duel->startTime)
auras2remove.push_back(i->second->GetId());
@ -7302,8 +7302,8 @@ void Player::ApplyEquipSpell(SpellEntry const* spellInfo, Item* item, bool apply
bool found = false;
for (int k=0; k < MAX_EFFECT_INDEX; ++k)
{
spellEffectPair spair = spellEffectPair(spellInfo->Id, SpellEffectIndex(k));
for (AuraMap::const_iterator iter = m_Auras.lower_bound(spair); iter != m_Auras.upper_bound(spair); ++iter)
SpellAuraHolderBounds spair = GetSpellAuraHolderBounds(spellInfo->Id);
for (SpellAuraHolderMap::const_iterator iter = spair.first; iter != spair.second; ++iter)
{
if(!item || iter->second->GetCastItemGUID() == item->GetGUID())
{
@ -15604,7 +15604,7 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
{
//RemoveAllAuras(); -- some spells casted before aura load, for example in LoadSkills, aura list explcitly cleaned early
//QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'",GetGUIDLow());
//QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,maxduration0,maxduration1,maxduration2,remaintime0,remaintime1,remaintime2,effIndexMask FROM character_aura WHERE guid = '%u'",GetGUIDLow());
if(result)
{
@ -15613,67 +15613,79 @@ void Player::_LoadAuras(QueryResult *result, uint32 timediff)
Field *fields = result->Fetch();
uint64 caster_guid = fields[0].GetUInt64();
uint32 spellid = fields[1].GetUInt32();
SpellEffectIndex effindex = SpellEffectIndex(fields[2].GetUInt32());
uint32 stackcount = fields[3].GetUInt32();
int32 damage = fields[4].GetInt32();
int32 maxduration = fields[5].GetInt32();
int32 remaintime = fields[6].GetInt32();
int32 remaincharges = fields[7].GetInt32();
uint32 stackcount = fields[2].GetUInt32();
int32 remaincharges = (int32)fields[3].GetUInt32();
int32 damage[MAX_EFFECT_INDEX];
int32 maxduration[MAX_EFFECT_INDEX];
int32 remaintime[MAX_EFFECT_INDEX];
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
damage[i] = (int32)fields[i+4].GetUInt32();
maxduration[i] = (int32)fields[i+7].GetUInt32();
remaintime[i] = (int32)fields[i+10].GetUInt32();
}
uint32 effIndexMask = (int32)fields[13].GetUInt32();
SpellEntry const* spellproto = sSpellStore.LookupEntry(spellid);
if (!spellproto)
if(!spellproto)
{
sLog.outError("Unknown aura (spellid %u, effindex %u), ignore.",spellid,effindex);
sLog.outError("Unknown spell (spellid %u), ignore.",spellid);
continue;
}
if (effindex >= MAX_EFFECT_INDEX)
{
sLog.outError("Invalid effect index (spellid %u, effindex %u), ignore.",spellid,effindex);
continue;
}
// negative effects should continue counting down after logout
if (remaintime != -1 && !IsPositiveEffect(spellid, effindex))
{
if (remaintime/IN_MILLISECONDS <= int32(timediff))
continue;
remaintime -= timediff*IN_MILLISECONDS;
}
// prevent wrong values of remaincharges
if (spellproto->procCharges)
if(spellproto->procCharges)
{
if (remaincharges <= 0 || remaincharges > (int32)spellproto->procCharges)
if(remaincharges <= 0 || remaincharges > (int32)spellproto->procCharges)
remaincharges = spellproto->procCharges;
}
else
remaincharges = 0;
if (spellproto->StackAmount < stackcount)
stackcount = spellproto->StackAmount;
for(uint32 i = 0; i < stackcount; ++i)
SpellAuraHolder *holder = CreateSpellAuraHolder(spellproto, this, NULL);
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
Aura* aura = CreateAura(spellproto, effindex, NULL, this, NULL);
if (!damage)
damage = aura->GetModifier()->m_amount;
if ((effIndexMask & (1 << i)) == 0)
continue;
// reset stolen single target auras
if (caster_guid != GetGUID() && aura->IsSingleTarget())
aura->SetIsSingleTarget(false);
if (remaintime[i] != -1 && !IsPositiveEffect(spellid, SpellEffectIndex(i)))
{
if (remaintime[i]/IN_MILLISECONDS <= int32(timediff))
continue;
aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges);
AddAura(aura);
DETAIL_LOG("Added aura spellid %u, effect %u", spellproto->Id, effindex);
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]);
holder->AddAura(aura, SpellEffectIndex(i));
}
if (!holder->IsEmptyHolder())
{
// reset stolen single target auras
if (caster_guid != GetGUID() && holder->IsSingleTarget())
holder->SetIsSingleTarget(false);
holder->SetLoadedState(caster_guid, stackcount, remaincharges);
AddSpellAuraHolder(holder);
DETAIL_LOG("Added auras from spellid %u, effect %u", spellproto->Id);
}
else
delete holder;
}
while( result->NextRow() );
delete result;
}
if(getClass() == CLASS_WARRIOR && !HasAuraType(SPELL_AURA_MOD_SHAPESHIFT))
CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true);
CastSpell(this,SPELL_ID_PASSIVE_BATTLE_STANCE,true);
}
void Player::_LoadGlyphs(QueryResult *result)
@ -16867,61 +16879,50 @@ void Player::_SaveAuras()
{
CharacterDatabase.PExecute("DELETE FROM character_aura WHERE guid = '%u'",GetGUIDLow());
AuraMap const& auras = GetAuras();
SpellAuraHolderMap const& auraHolders = GetSpellAuraHolderMap();
if (auras.empty())
if (auraHolders.empty())
return;
spellEffectPair lastEffectPair = auras.begin()->first;
uint32 stackCounter = 1;
/* copied following sql-code partly from achievementmgr */
bool first_round = true;
std::ostringstream ss;
for(AuraMap::const_iterator itr = auras.begin(); ; ++itr)
for(SpellAuraHolderMap::const_iterator itr = auraHolders.begin(); itr != auraHolders.end(); ++itr)
{
if(itr == auras.end() || lastEffectPair != itr->first)
SpellAuraHolder *holder = itr->second;
//skip all holders from spells that are passive
//do not save single target holders (unless they were cast by the player)
if (!holder->IsPassive() && (holder->GetCasterGUID() == GetGUID() || !holder->IsSingleTarget()))
{
AuraMap::const_iterator itr2 = itr;
// save previous spellEffectPair to db
itr2--;
int32 damage[MAX_EFFECT_INDEX];
int32 remaintime[MAX_EFFECT_INDEX];
int32 maxduration[MAX_EFFECT_INDEX];
uint32 effIndexMask = 0;
//skip all auras from spells that are passive
//do not save single target auras (unless they were cast by the player)
if (!itr2->second->IsPassive() && (itr2->second->GetCasterGUID() == GetGUID() || !itr2->second->IsSingleTarget()))
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if (first_round)
damage[i] = 0;
remaintime[i] = 0;
maxduration[i] = 0;
if (Aura *aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i)))
{
ss << "INSERT INTO character_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges)VALUES ";
first_round = false;
// don't save not own area auras
if (aur->IsAreaAura() && holder->GetCasterGUID() != GetGUID())
continue;
damage[i] = aur->GetModifier()->m_amount;
remaintime[i] = aur->GetAuraDuration();
maxduration[i] = aur->GetAuraMaxDuration();
effIndexMask |= (1 << i);
}
// next new/changed record prefix
else
ss << ", ";
ss << "("<< GetGUIDLow() << "," << itr2->second->GetCasterGUID() << ","
<< (uint32)itr2->second->GetId() << "," << (uint32)itr2->second->GetEffIndex() << ","
<< stackCounter << "," << itr2->second->GetModifier()->m_amount << ","
<<int(itr2->second->GetAuraMaxDuration()) << "," << int(itr2->second->GetAuraDuration()) << ","
<< int(itr2->second->GetAuraCharges()) << ")";
}
if (!effIndexMask)
continue;
if(itr == auras.end())
break;
}
if (lastEffectPair == itr->first)
stackCounter++;
else
{
lastEffectPair = itr->first;
stackCounter = 1;
CharacterDatabase.PExecute("INSERT INTO character_aura (guid, caster_guid, spell, stackcount, remaincharges, basepoints0, basepoints1, basepoints2, maxduration0, maxduration1, maxduration2, remaintime0, remaintime1, remaintime2, effIndexMask) VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%d', '%u')", GetGUIDLow(), holder->GetCasterGUID(), holder->GetId(), holder->GetStackAmount(), holder->GetAuraCharges(), damage[EFFECT_INDEX_0], damage[EFFECT_INDEX_1], damage[EFFECT_INDEX_2], maxduration[EFFECT_INDEX_0], maxduration[EFFECT_INDEX_1], maxduration[EFFECT_INDEX_2], remaintime[EFFECT_INDEX_0], remaintime[EFFECT_INDEX_1], remaintime[EFFECT_INDEX_2], effIndexMask);
}
}
// if something changed execute
if (!first_round)
CharacterDatabase.Execute( ss.str().c_str() );
}
void Player::_SaveGlyphs()
@ -19750,38 +19751,51 @@ void Player::SendAurasForTarget(Unit *target)
Unit::VisibleAuraMap const *visibleAuras = target->GetVisibleAuras();
for(Unit::VisibleAuraMap::const_iterator itr = visibleAuras->begin(); itr != visibleAuras->end(); ++itr)
{
for(int j = 0; j < MAX_EFFECT_INDEX; ++j)
SpellAuraHolderBounds bounds = target->GetSpellAuraHolderBounds(itr->second);
for (SpellAuraHolderMap::const_iterator iter = bounds.first; iter != bounds.second; ++iter)
{
if(Aura *aura = target->GetAura(itr->second, SpellEffectIndex(j)))
SpellAuraHolder *holder = iter->second;
data << uint8(holder->GetAuraSlot());
data << uint32(holder->GetId());
if(holder->GetId())
{
data << uint8(aura->GetAuraSlot());
data << uint32(aura->GetId());
uint8 auraFlags = holder->GetAuraFlags();
// flags
data << uint8(auraFlags);
// level
data << uint8(holder->GetAuraLevel());
// charges
if (holder->GetAuraCharges())
data << uint8(holder->GetAuraCharges() * holder->GetStackAmount());
else
data << uint8(holder->GetStackAmount());
if(aura->GetId())
if(!(auraFlags & AFLAG_NOT_CASTER)) // packed GUID of caster
{
uint8 auraFlags = aura->GetAuraFlags();
// flags
data << uint8(auraFlags);
// level
data << uint8(aura->GetAuraLevel());
// charges
if (aura->GetAuraCharges())
data << uint8(aura->GetAuraCharges() * aura->GetStackAmount());
else
data << uint8(aura->GetStackAmount());
if(!(auraFlags & AFLAG_NOT_CASTER)) // packed GUID of caster
{
data.appendPackGUID(aura->GetCasterGUID());
}
if(auraFlags & AFLAG_DURATION) // include aura duration
{
data << uint32(aura->GetAuraMaxDuration());
data << uint32(aura->GetAuraDuration());
}
data.appendPackGUID(holder->GetCasterGUID());
}
if(auraFlags & AFLAG_DURATION) // include aura 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 = holder->GetAuraByEffectIndex(SpellEffectIndex(i)))
{
if (uint32(aura->GetAuraMaxDuration()) > max_duration)
{
max_duration = aura->GetAuraMaxDuration();
duration = aura->GetAuraDuration();
}
}
}
data << uint32(max_duration);
data << uint32(duration);
}
break;
}
}
}
@ -20121,14 +20135,14 @@ bool Player::CanNoReagentCast(SpellEntry const* spellInfo) const
void Player::RemoveItemDependentAurasAndCasts( Item * pItem )
{
AuraMap& auras = GetAuras();
for(AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); )
SpellAuraHolderMap& auras = GetSpellAuraHolderMap();
for(SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); )
{
Aura* aura = itr->second;
SpellAuraHolder* holder = itr->second;
// skip passive (passive item dependent spells work in another way) and not self applied auras
SpellEntry const* spellInfo = aura->GetSpellProto();
if(aura->IsPassive() || aura->GetCasterGUID()!=GetGUID())
SpellEntry const* spellInfo = holder->GetSpellProto();
if(holder->IsPassive() || holder->GetCasterGUID()!=GetGUID())
{
++itr;
continue;
@ -20142,7 +20156,7 @@ void Player::RemoveItemDependentAurasAndCasts( Item * pItem )
}
// no alt item, remove aura, restart check
RemoveAurasDueToSpell(aura->GetId());
RemoveAurasDueToSpell(holder->GetId());
itr = auras.begin();
}
@ -20369,11 +20383,14 @@ void Player::UpdateZoneDependentAuras( uint32 newZone )
void Player::UpdateAreaDependentAuras( uint32 newArea )
{
// remove auras from spells with area limitations
for(AuraMap::iterator iter = m_Auras.begin(); iter != m_Auras.end();)
for(SpellAuraHolderMap::iterator iter = m_spellAuraHolders.begin(); iter != m_spellAuraHolders.end();)
{
// use m_zoneUpdateId for speed: UpdateArea called from UpdateZone or instead UpdateZone in both cases m_zoneUpdateId up-to-date
if(sSpellMgr.GetSpellAllowedInLocationError(iter->second->GetSpellProto(),GetMapId(),m_zoneUpdateId,newArea,this) != SPELL_CAST_OK)
RemoveAura(iter);
{
RemoveSpellAuraHolder(iter->second);
iter = m_spellAuraHolders.begin();
}
else
++iter;
}