[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

@ -75,7 +75,7 @@ bool LoginQueryHolder::Initialize()
"health, power1, power2, power3, power4, power5, power6, power7, specCount, activeSpec, exploredZones, equipmentCache, ammoId, knownTitles, actionBars FROM characters WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADGROUP, "SELECT groupId FROM group_member WHERE memberGuid ='%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADBOUNDINSTANCES, "SELECT id, permanent, map, difficulty, resettime FROM character_instance LEFT JOIN instance ON instance = id WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADAURAS, "SELECT caster_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,maxduration0,maxduration1,maxduration2,remaintime0,remaintime1,remaintime2,effIndexMask FROM character_aura WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADSPELLS, "SELECT spell,active,disabled FROM character_spell WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADQUESTSTATUS, "SELECT quest,status,rewarded,explored,timer,mobcount1,mobcount2,mobcount3,mobcount4,itemcount1,itemcount2,itemcount3,itemcount4 FROM character_queststatus WHERE guid = '%u'", GUID_LOPART(m_guid));
res &= SetPQuery(PLAYER_LOGIN_QUERY_LOADDAILYQUESTSTATUS,"SELECT quest FROM character_queststatus_daily WHERE guid = '%u'", GUID_LOPART(m_guid));

View file

@ -1814,9 +1814,27 @@ bool Creature::LoadCreaturesAddon(bool reload)
continue;
}
Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, cAura->effect_idx, NULL, this, this, 0);
AddAura(AdditionalAura);
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell: %u with Aura %u added to creature (GUIDLow: %u Entry: %u )", cAura->spell_id, AdditionalSpellInfo->EffectApplyAuraName[EFFECT_INDEX_0],GetGUIDLow(),GetEntry());
SpellAuraHolder *holder = GetSpellAuraHolder(cAura->spell_id, GetGUID());
bool addedToExisting = true;
if (!holder)
{
holder = CreateSpellAuraHolder(AdditionalSpellInfo, this, this);
addedToExisting = false;
}
Aura* AdditionalAura = CreateAura(AdditionalSpellInfo, cAura->effect_idx, NULL, holder, this, this, 0);
holder->AddAura(AdditionalAura, cAura->effect_idx);
if (addedToExisting)
{
holder->SetInUse(true);
AdditionalAura->ApplyModifier(true,true);
holder->SetInUse(false);
}
else
AddSpellAuraHolder(holder);
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell: %u - Aura %u added to creature (GUIDLow: %u Entry: %u )", cAura->spell_id, AdditionalSpellInfo->EffectApplyAuraName[EFFECT_INDEX_0],GetGUIDLow(),GetEntry());
}
}
return true;

View file

@ -291,10 +291,8 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
break;
case EVENT_T_BUFFED:
{
//Note: checked only aura for effect 0, if need check aura for effect 1/2 then
// possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
Aura* aura = m_creature->GetAura(event.buffed.spellId, EFFECT_INDEX_0);
if (!aura || aura->GetStackAmount() < event.buffed.amount)
SpellAuraHolder* holder = m_creature->GetSpellAuraHolder(event.buffed.spellId);
if (!holder || holder->GetStackAmount() < event.buffed.amount)
return false;
//Repeat Timers
@ -307,10 +305,8 @@ bool CreatureEventAI::ProcessEvent(CreatureEventAIHolder& pHolder, Unit* pAction
if (!pActionInvoker)
return false;
//Note: checked only aura for effect 0, if need check aura for effect 1/2 then
// possible way: pack in event.buffed.amount 2 uint16 (ammount+effectIdx)
Aura* aura = pActionInvoker->GetAura(event.buffed.spellId, EFFECT_INDEX_0);
if(!aura || aura->GetStackAmount() < event.buffed.amount)
SpellAuraHolder* holder = pActionInvoker->GetSpellAuraHolder(event.buffed.spellId);
if(!holder || holder->GetStackAmount() < event.buffed.amount)
return false;
//Repeat Timers

View file

@ -149,7 +149,7 @@ void DynamicObject::Delay(int32 delaytime)
m_aliveDuration -= delaytime;
for(AffectedSet::iterator iunit= m_affected.begin(); iunit != m_affected.end(); ++iunit)
if (*iunit)
(*iunit)->DelayAura(m_spellId, m_effIndex, delaytime);
(*iunit)->DelaySpellAuraHolder(m_spellId, delaytime);
}
bool DynamicObject::isVisibleForInState(Player const* u, WorldObject const* viewPoint, bool inVisibleList) const

View file

@ -172,8 +172,28 @@ inline void MaNGOS::DynamicObjectUpdater::VisitHelper(Unit* target)
return;
// Apply PersistentAreaAura on target
PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, target, i_dynobject.GetCaster());
target->AddAura(Aur);
SpellAuraHolder *holder = target->GetSpellAuraHolder(spellInfo->Id, i_dynobject.GetCaster()->GetGUID());
bool addedToExisting = true;
if (!holder)
{
holder = CreateSpellAuraHolder(spellInfo, target, i_dynobject.GetCaster());
addedToExisting = false;
}
PersistentAreaAura* Aur = new PersistentAreaAura(spellInfo, eff_index, NULL, holder, target, i_dynobject.GetCaster());
holder->AddAura(Aur, eff_index);
if (addedToExisting)
{
holder->SetInUse(true);
Aur->ApplyModifier(true,true);
holder->SetInUse(false);
}
else
target->AddSpellAuraHolder(holder);
i_dynobject.AddAffected(target);
}

View file

@ -3563,6 +3563,10 @@ bool ChatHandler::HandleAuraCommand(const char* args)
SpellEntry const *spellInfo = sSpellStore.LookupEntry( spellID );
if(spellInfo)
{
SpellAuraHolder *holder = NULL;
if (IsSpellAppliesAura(spellInfo, (1 << EFFECT_INDEX_0) | (1 << EFFECT_INDEX_1) | (1 << EFFECT_INDEX_2)) || IsSpellHaveEffect(spellInfo, SPELL_EFFECT_PERSISTENT_AREA_AURA))
holder = CreateSpellAuraHolder(spellInfo, target, m_session->GetPlayer());
for(uint32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
uint8 eff = spellInfo->Effect[i];
@ -3572,10 +3576,11 @@ bool ChatHandler::HandleAuraCommand(const char* args)
eff == SPELL_EFFECT_APPLY_AURA ||
eff == SPELL_EFFECT_PERSISTENT_AREA_AURA )
{
Aura *Aur = CreateAura(spellInfo, SpellEffectIndex(i), NULL, target);
target->AddAura(Aur);
Aura *aur = CreateAura(spellInfo, SpellEffectIndex(i), NULL, holder, target);
holder->AddAura(aur, SpellEffectIndex(i));
}
}
target->AddSpellAuraHolder(holder);
}
return true;
@ -4252,32 +4257,40 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/)
char const* talentStr = GetMangosString(LANG_TALENT);
char const* passiveStr = GetMangosString(LANG_PASSIVE);
Unit::AuraMap const& uAuras = unit->GetAuras();
Unit::SpellAuraHolderMap const& uAuras = unit->GetSpellAuraHolderMap();
PSendSysMessage(LANG_COMMAND_TARGET_LISTAURAS, uAuras.size());
for (Unit::AuraMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr)
for (Unit::SpellAuraHolderMap::const_iterator itr = uAuras.begin(); itr != uAuras.end(); ++itr)
{
bool talent = GetTalentSpellCost(itr->second->GetId()) > 0;
SpellAuraHolder *holder = itr->second;
char const* name = holder->GetSpellProto()->SpellName[GetSessionDbcLocale()];
char const* name = itr->second->GetSpellProto()->SpellName[GetSessionDbcLocale()];
if (m_session)
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
std::ostringstream ss_name;
ss_name << "|cffffffff|Hspell:" << itr->second->GetId() << "|h[" << name << "]|h|r";
Aura *aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i));
if (!aur)
continue;
if (m_session)
{
std::ostringstream ss_name;
ss_name << "|cffffffff|Hspell:" << itr->second->GetId() << "|h[" << name << "]|h|r";
PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(),
itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(),
ss_name.str().c_str(),
(itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID()));
}
else
{
PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, itr->second->GetId(), itr->second->GetEffIndex(),
itr->second->GetModifier()->m_auraname, itr->second->GetAuraDuration(), itr->second->GetAuraMaxDuration(),
name,
(itr->second->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
IS_PLAYER_GUID(itr->second->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(itr->second->GetCasterGUID()));
PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, holder->GetId(), aur->GetEffIndex(),
aur->GetModifier()->m_auraname, aur->GetAuraDuration(), aur->GetAuraMaxDuration(),
ss_name.str().c_str(),
(holder->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
IS_PLAYER_GUID(holder->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(holder->GetCasterGUID()));
}
else
{
PSendSysMessage(LANG_COMMAND_TARGET_AURADETAIL, holder->GetId(), aur->GetEffIndex(),
aur->GetModifier()->m_auraname, aur->GetAuraDuration(), aur->GetAuraMaxDuration(),
name,
(holder->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
IS_PLAYER_GUID(holder->GetCasterGUID()) ? "player" : "creature",GUID_LOPART(holder->GetCasterGUID()));
}
}
}
for (int i = 0; i < TOTAL_AURAS; ++i)
@ -4297,13 +4310,13 @@ bool ChatHandler::HandleListAurasCommand (const char * /*args*/)
ss_name << "|cffffffff|Hspell:" << (*itr)->GetId() << "|h[" << name << "]|h|r";
PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(),
ss_name.str().c_str(),((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
ss_name.str().c_str(),((*itr)->GetHolder()->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID()));
}
else
{
PSendSysMessage(LANG_COMMAND_TARGET_AURASIMPLE, (*itr)->GetId(), (*itr)->GetEffIndex(),
name,((*itr)->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
name,((*itr)->GetHolder()->IsPassive() ? passiveStr : ""),(talent ? talentStr : ""),
IS_PLAYER_GUID((*itr)->GetCasterGUID()) ? "player" : "creature",GUID_LOPART((*itr)->GetCasterGUID()));
}
}

View file

@ -7490,8 +7490,8 @@ bool PlayerCondition::Meets(Player const * player) const
}
case CONDITION_AD_COMMISSION_AURA:
{
Unit::AuraMap const& auras = player->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = player->GetSpellAuraHolderMap();
for (Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
if ((itr->second->GetSpellProto()->Attributes & 0x1000010) && itr->second->GetSpellProto()->SpellVisual[0]==3580)
return true;
return false;

View file

@ -1143,8 +1143,8 @@ void Pet::_SaveSpells()
void Pet::_LoadAuras(uint32 timediff)
{
RemoveAllAuras();
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
QueryResult *result = CharacterDatabase.PQuery("SELECT caster_guid,spell,stackcount,remaincharges,basepoints0,basepoints1,basepoints2,maxduration0,maxduration1,maxduration2,remaintime0,remaintime1,remaintime2,effIndexMask FROM pet_aura WHERE guid = '%u'",m_charmInfo->GetPetNumber());
if(result)
{
@ -1153,34 +1153,29 @@ void Pet::_LoadAuras(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 = (int32)fields[4].GetUInt32();
int32 maxduration = (int32)fields[5].GetUInt32();
int32 remaintime = (int32)fields[6].GetUInt32();
int32 remaincharges = (int32)fields[7].GetUInt32();
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)
{
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);
// do not load single target auras (unless they were cast by the player)
if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
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)
@ -1191,19 +1186,38 @@ void Pet::_LoadAuras(uint32 timediff)
else
remaincharges = 0;
/// do not load single target auras (unless they were cast by the player)
if (caster_guid != GetGUID() && IsSingleTargetSpell(spellproto))
continue;
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 ((effIndexMask & (1 << i)) == 0)
continue;
if(!damage)
damage = aura->GetModifier()->m_amount;
aura->SetLoadedState(caster_guid,damage,maxduration,remaintime,remaincharges);
AddAura(aura);
if (remaintime[i] != -1 && !IsPositiveEffect(spellid, 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]);
holder->AddAura(aura, SpellEffectIndex(i));
}
if (!holder->IsEmptyHolder())
{
holder->SetLoadedState(caster_guid, stackcount, remaincharges);
AddSpellAuraHolder(holder);
}
else
delete holder;
}
while( result->NextRow() );
@ -1215,52 +1229,60 @@ void Pet::_SaveAuras()
{
CharacterDatabase.PExecute("DELETE FROM pet_aura WHERE guid = '%u'", m_charmInfo->GetPetNumber());
AuraMap const& auras = GetAuras();
if (auras.empty())
SpellAuraHolderMap const& auraHolders = GetSpellAuraHolderMap();
if (auraHolders.empty())
return;
spellEffectPair lastEffectPair = auras.begin()->first;
uint32 stackCounter = 1;
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)
{
AuraMap::const_iterator itr2 = itr;
// save previous spellEffectPair to db
itr2--;
SpellEntry const *spellInfo = itr2->second->GetSpellProto();
/// do not save single target auras (unless they were cast by the player)
if (!(itr2->second->GetCasterGUID() != GetGUID() && IsSingleTargetSpell(spellInfo)))
{
if(!itr2->second->IsPassive())
{
// skip all auras from spell that apply at cast SPELL_AURA_MOD_SHAPESHIFT or pet area auras.
uint8 i;
for (i = 0; i < MAX_EFFECT_INDEX; ++i)
if (spellInfo->EffectApplyAuraName[i] == SPELL_AURA_MOD_STEALTH ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER ||
spellInfo->Effect[i] == SPELL_EFFECT_APPLY_AREA_AURA_PET )
break;
SpellAuraHolder *holder = itr->second;
if (i == 3)
{
CharacterDatabase.PExecute("INSERT INTO pet_aura (guid,caster_guid,spell,effect_index,stackcount,amount,maxduration,remaintime,remaincharges) "
"VALUES ('%u', '" UI64FMTD "', '%u', '%u', '%u', '%d', '%d', '%d', '%d')",
m_charmInfo->GetPetNumber(), 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(itr == auras.end())
bool save = true;
for (int32 j = 0; j < MAX_EFFECT_INDEX; ++j)
{
SpellEntry const* spellInfo = holder->GetSpellProto();
if (spellInfo->EffectApplyAuraName[j] == SPELL_AURA_MOD_STEALTH ||
spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AREA_AURA_OWNER ||
spellInfo->Effect[j] == SPELL_EFFECT_APPLY_AREA_AURA_PET )
{
save = false;
break;
}
}
if (lastEffectPair == itr->first)
stackCounter++;
else
//skip all holders from spells that are passive
//do not save single target holders (unless they were cast by the player)
if (save && !holder->IsPassive() && (holder->GetCasterGUID() == GetGUID() || !holder->IsSingleTarget()))
{
lastEffectPair = itr->first;
stackCounter = 1;
int32 damage[MAX_EFFECT_INDEX];
int32 remaintime[MAX_EFFECT_INDEX];
int32 maxduration[MAX_EFFECT_INDEX];
uint32 effIndexMask = 0;
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
damage[i] = 0;
remaintime[i] = 0;
maxduration[i] = 0;
if (Aura *aur = holder->GetAuraByEffectIndex(SpellEffectIndex(i)))
{
// 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);
}
}
if (!effIndexMask)
continue;
CharacterDatabase.PExecute("INSERT INTO pet_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')", m_charmInfo->GetPetNumber(), 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);
}
}
}

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;
}

View file

@ -1060,12 +1060,11 @@ void Spell::DoAllEffectOnTarget(TargetInfo *target)
if (m_spellInfo->SpellFamilyName == SPELLFAMILY_DEATHKNIGHT && m_spellInfo->SpellFamilyFlags & UI64LIT(0x0800000000000000))
{
uint32 count = 0;
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
{
if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
itr->second->GetCasterGUID() == caster->GetGUID() &&
IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
itr->second->GetCasterGUID() == caster->GetGUID())
++count;
}
@ -1219,6 +1218,11 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
// Apply additional spell effects to target
CastPreCastSpells(unit);
if (IsSpellAppliesAura(m_spellInfo, effectMask))
spellAuraHolder = CreateSpellAuraHolder(m_spellInfo, unit, realCaster, m_CastItem);
else
spellAuraHolder = NULL;
for(int effectNumber = 0; effectNumber < MAX_EFFECT_INDEX; ++effectNumber)
{
if (effectMask & (1 << effectNumber))
@ -1236,6 +1240,16 @@ void Spell::DoSpellHitOnUnit(Unit *unit, const uint32 effectMask)
}
}
}
// now apply all created auras
if (spellAuraHolder)
{
// normally shouldn't happen
if (!spellAuraHolder->IsEmptyHolder())
unit->AddSpellAuraHolder(spellAuraHolder);
else
delete spellAuraHolder;
}
}
void Spell::DoAllEffectOnTarget(GOTargetInfo *target)
@ -5378,43 +5392,48 @@ SpellCastResult Spell::CheckCasterAuras() const
if (school_immune || mechanic_immune || dispel_immune)
{
//Checking auras is needed now, because you are prevented by some state but the spell grants immunity.
Unit::AuraMap const& auras = m_caster->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = m_caster->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
{
if (itr->second)
if (SpellAuraHolder *holder = itr->second)
{
if (GetSpellMechanicMask(itr->second->GetSpellProto(), itr->second->GetEffIndex()) & mechanic_immune)
continue;
if (GetSpellSchoolMask(itr->second->GetSpellProto()) & school_immune)
continue;
if ((1<<(itr->second->GetSpellProto()->Dispel)) & dispel_immune)
continue;
// Make a second check for spell failed so the right SPELL_FAILED message is returned.
// That is needed when your casting is prevented by multiple states and you are only immune to some of them.
switch(itr->second->GetModifier()->m_auraname)
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
case SPELL_AURA_MOD_STUN:
if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED))
return SPELL_FAILED_STUNNED;
break;
case SPELL_AURA_MOD_CONFUSE:
if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED))
return SPELL_FAILED_CONFUSED;
break;
case SPELL_AURA_MOD_FEAR:
if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED))
return SPELL_FAILED_FLEEING;
break;
case SPELL_AURA_MOD_SILENCE:
case SPELL_AURA_MOD_PACIFY:
case SPELL_AURA_MOD_PACIFY_SILENCE:
if( m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY)
return SPELL_FAILED_PACIFIED;
else if ( m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
return SPELL_FAILED_SILENCED;
break;
default: break;
if (GetSpellMechanicMask(itr->second->GetSpellProto(), i) & mechanic_immune)
continue;
if (GetSpellSchoolMask(itr->second->GetSpellProto()) & school_immune)
continue;
if ((1<<(itr->second->GetSpellProto()->Dispel)) & dispel_immune)
continue;
Aura *aura = holder->GetAuraByEffectIndex(SpellEffectIndex(i));
if (!aura)
continue;
// Make a second check for spell failed so the right SPELL_FAILED message is returned.
// That is needed when your casting is prevented by multiple states and you are only immune to some of them.
switch(aura->GetModifier()->m_auraname)
{
case SPELL_AURA_MOD_STUN:
if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_STUNNED))
return SPELL_FAILED_STUNNED;
break;
case SPELL_AURA_MOD_CONFUSE:
if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_CONFUSED))
return SPELL_FAILED_CONFUSED;
break;
case SPELL_AURA_MOD_FEAR:
if (!(m_spellInfo->AttributesEx5 & SPELL_ATTR_EX5_USABLE_WHILE_FEARED))
return SPELL_FAILED_FLEEING;
break;
case SPELL_AURA_MOD_SILENCE:
case SPELL_AURA_MOD_PACIFY:
case SPELL_AURA_MOD_PACIFY_SILENCE:
if( m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_PACIFY)
return SPELL_FAILED_PACIFIED;
else if ( m_spellInfo->PreventionType == SPELL_PREVENTION_TYPE_SILENCE)
return SPELL_FAILED_SILENCED;
break;
default: break;
}
}
}
}
@ -6131,10 +6150,7 @@ void Spell::DelayedChannel()
if ((*ihit).missCondition == SPELL_MISS_NONE)
{
if (Unit* unit = m_caster->GetObjectGuid() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID))
for (int j = 0; j < MAX_EFFECT_INDEX; ++j)
if (ihit->effectMask & (1 << j))
unit->DelayAura(m_spellInfo->Id, SpellEffectIndex(j), delaytime);
unit->DelaySpellAuraHolder(m_spellInfo->Id, delaytime);
}
}

View file

@ -529,6 +529,7 @@ class Spell
Unit* unitTarget;
Item* itemTarget;
GameObject* gameObjTarget;
SpellAuraHolder* spellAuraHolder; // spell aura holder for current target, created only if spell has aura applying effect
int32 damage;
// this is set in Spell Hit, but used in Apply Aura handler

File diff suppressed because it is too large Load diff

View file

@ -40,6 +40,150 @@ class Aura;
// internal helper
struct ReapplyAffectedPassiveAurasHelper;
class MANGOS_DLL_SPEC SpellAuraHolder
{
public:
SpellAuraHolder (SpellEntry const* spellproto, Unit *target, WorldObject *caster, Item *castItem);
Aura* m_auras[MAX_EFFECT_INDEX];
void AddAura(Aura *aura, SpellEffectIndex index);
void RemoveAura(SpellEffectIndex index);
void ApplyAuraModifiers(bool apply, bool real = false);
void _AddSpellAuraHolder();
void _RemoveSpellAuraHolder();
void SendAuraUpdate(bool remove);
void HandleSpellSpecificBoosts(bool apply);
void CleanupTriggeredSpells();
void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }
DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; }
uint8 GetStackAmount() { return m_stackAmount; }
void SetStackAmount(uint8 stackAmount);
bool ModStackAmount(int32 num); // return true if last charge dropped
Aura* GetAuraByEffectIndex(SpellEffectIndex index) const
{
if (Aura *aur = m_auras[index])
return aur;
else
return NULL;
}
uint32 GetId() const { return m_spellProto->Id; }
SpellEntry const* GetSpellProto() const { return m_spellProto; }
uint64 const& GetCasterGUID() const { return m_caster_guid; }
void SetCasterGUID(uint64 guid) { m_caster_guid = guid; }
uint64 GetCastItemGUID() const { return m_castItemGuid; }
Unit* GetCaster() const;
Unit* GetTarget() const { return m_target; }
void SetTarget(Unit* target) { m_target = target; }
bool IsPermanent() const { return m_permanent; }
void SetPermanent (bool permanent) { m_permanent = permanent; }
bool IsPassive() const { return m_isPassive; }
bool IsDeathPersistent() const { return m_isDeathPersist; }
bool IsPersistent() const;
bool IsPositive() const;
bool IsWeaponBuffCoexistableWith(SpellAuraHolder* ref);
bool IsNeedVisibleSlot(Unit const* caster) const;
bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; }
bool IsInUse() const { return m_in_use;}
bool IsDeleted() const { return m_deleted;}
bool IsEmptyHolder() const;
void SetInUse(bool state)
{
if(state)
++m_in_use;
else
{
if(m_in_use)
--m_in_use;
}
}
void UpdateHolder(uint32 diff) { SetInUse(true); Update(diff); SetInUse(false); }
void Update(uint32 diff);
void RefreshHolder();
bool IsSingleTarget() {return m_isSingleTarget; }
void SetIsSingleTarget(bool val) { m_isSingleTarget = val; }
void UnregisterSingleCastHolder();
uint8 GetAuraSlot() const { return m_auraSlot; }
void SetAuraSlot(uint8 slot) { m_auraSlot = slot; }
uint8 GetAuraFlags() const { return m_auraFlags; }
void SetAuraFlags(uint8 flags) { m_auraFlags = flags; }
uint8 GetAuraLevel() const { return m_auraLevel; }
void SetAuraLevel(uint8 level) { m_auraLevel = level; }
uint8 GetAuraCharges() const { return m_procCharges; }
void SetAuraCharges(uint8 charges)
{
if (m_procCharges == charges)
return;
m_procCharges = charges;
SendAuraUpdate(false);
}
bool DropAuraCharge() // return true if last charge dropped
{
if (m_procCharges == 0)
return false;
// exist spells that have maxStack > 1 and m_procCharges > 0 (==1 in fact)
// all like stacks have 1 value in one from this fields
// so return true for allow remove one aura from stacks as expired
if (GetStackAmount() > 1)
return true;
m_procCharges--;
SendAuraUpdate(false);
return m_procCharges == 0;
}
time_t GetAuraApplyTime() const { return m_applyTime; }
void SetVisibleAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); }
void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; }
void SetLoadedState(uint64 casterGUID, int32 stackAmount, int32 charges)
{
m_caster_guid = casterGUID;
m_procCharges = charges;
m_stackAmount = stackAmount;
}
bool HasAuraAndMechanicEffect(uint32 mechanic) const;
bool HasAuraAndMechanicEffectMask(uint32 mechanicMask) const;
~SpellAuraHolder();
private:
Unit* m_target;
uint64 m_caster_guid;
uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
time_t m_applyTime;
SpellEntry const* m_spellProto;
uint8 m_auraSlot; // Aura slot on unit (for show in client)
uint8 m_auraFlags; // Aura info flag (for send data to client)
uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount)
uint8 m_procCharges; // Aura charges (0 for infinite)
uint8 m_stackAmount; // Aura stack amount
AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason
DiminishingGroup m_AuraDRGroup:8; // Diminishing
bool m_permanent:1;
bool m_isPassive:1;
bool m_isDeathPersist:1;
bool m_isRemovedOnShapeLost:1;
bool m_isSingleTarget:1; // true if it's a single target spell and registered at caster - can change at spell steal for example
bool m_deleted:1;
uint32 m_in_use; // > 0 while in SpellAuraHolder::ApplyModifiers call/SpellAuraHolder::Update/etc
};
typedef void(Aura::*pAuraHandler)(bool Apply, bool Real);
// Real == true at aura add/remove
// Real == false at aura mod unapply/reapply; when adding/removing dependent aura/item/stat mods
@ -57,7 +201,7 @@ typedef void(Aura::*pAuraHandler)(bool Apply, bool Real);
class MANGOS_DLL_SPEC Aura
{
friend struct ReapplyAffectedPassiveAurasHelper;
friend Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem);
friend Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster, Item* castItem);
public:
//aura handlers
@ -226,12 +370,16 @@ class MANGOS_DLL_SPEC Aura
void SetModifier(AuraType t, int32 a, uint32 pt, int32 miscValue);
Modifier* GetModifier() { return &m_modifier; }
Modifier const* GetModifier() const { return &m_modifier; }
int32 GetMiscValue() const { return m_spellProto->EffectMiscValue[m_effIndex]; }
int32 GetMiscBValue() const { return m_spellProto->EffectMiscValueB[m_effIndex]; }
int32 GetMiscValue() const { return m_spellAuraHolder->GetSpellProto()->EffectMiscValue[m_effIndex]; }
int32 GetMiscBValue() const { return m_spellAuraHolder->GetSpellProto()->EffectMiscValueB[m_effIndex]; }
SpellEntry const* GetSpellProto() const { return GetHolder()->GetSpellProto(); }
uint32 GetId() const{ return GetHolder()->GetSpellProto()->Id; }
uint64 GetCastItemGUID() const { return GetHolder()->GetCastItemGUID(); }
uint64 const& GetCasterGUID() const { return GetHolder()->GetCasterGUID(); }
Unit* GetCaster() const { return GetHolder()->GetCaster(); }
Unit* GetTarget() const { return GetHolder()->GetTarget(); }
SpellEntry const* GetSpellProto() const { return m_spellProto; }
uint32 GetId() const{ return m_spellProto->Id; }
uint64 GetCastItemGUID() const { return m_castItemGuid; }
SpellEffectIndex GetEffIndex() const{ return m_effIndex; }
int32 GetBasePoints() const { return m_currentBasePoints; }
@ -242,76 +390,23 @@ class MANGOS_DLL_SPEC Aura
time_t GetAuraApplyTime() const { return m_applyTime; }
uint32 GetAuraTicks() const { return m_periodicTick; }
uint32 GetAuraMaxTicks() const { return m_maxduration > 0 && m_modifier.periodictime > 0 ? m_maxduration / m_modifier.periodictime : 0; }
uint8 GetStackAmount() const { return GetHolder()->GetStackAmount(); }
uint64 const& GetCasterGUID() const { return m_caster_guid; }
Unit* GetCaster() const;
Unit* GetTarget() const { return m_target; }
void SetTarget(Unit* target) { m_target = target; }
void SetLoadedState(uint64 caster_guid,int32 damage,int32 maxduration,int32 duration,int32 charges)
void SetLoadedState(int32 damage,int32 maxduration,int32 duration)
{
m_caster_guid = caster_guid;
m_modifier.m_amount = damage;
SetAuraMaxDuration(maxduration);
SetAuraDuration(duration);
m_procCharges = charges;
if(uint32 maxticks = GetAuraMaxTicks())
m_periodicTick = maxticks - m_duration / m_modifier.periodictime;
}
uint8 GetAuraSlot() const { return m_auraSlot; }
void SetAuraSlot(uint8 slot) { m_auraSlot = slot; }
uint8 GetAuraFlags() const { return m_auraFlags; }
void SetAuraFlags(uint8 flags) { m_auraFlags = flags; }
uint8 GetAuraLevel() const { return m_auraLevel; }
void SetAuraLevel(uint8 level) { m_auraLevel = level; }
uint8 GetAuraCharges() const { return m_procCharges; }
void SetAuraCharges(uint8 charges)
{
if (m_procCharges == charges)
return;
m_procCharges = charges;
SendAuraUpdate(false);
}
bool DropAuraCharge() // return true if last charge dropped
{
if (m_procCharges == 0)
return false;
// exist spells that have maxStack > 1 and m_procCharges > 0 (==1 in fact)
// all like stacks have 1 value in one from this fields
// so return true for allow remove one aura from stacks as expired
if (GetStackAmount() > 1)
return true;
m_procCharges--;
SendAuraUpdate(false);
return m_procCharges == 0;
}
void UnregisterSingleCastAura();
void SetAura(bool remove) { m_target->SetVisibleAura(m_auraSlot, remove ? 0 : GetId()); }
void SendAuraUpdate(bool remove);
uint8 GetStackAmount() {return m_stackAmount;}
void SetStackAmount(uint8 num);
bool modStackAmount(int32 num); // return true if last charge dropped
void RefreshAura();
bool IsPositive() { return m_positive; }
void SetNegative() { m_positive = false; }
void SetPositive() { m_positive = true; }
bool IsPermanent() const { return m_permanent; }
bool IsPersistent() const { return m_isPersistent; }
bool IsAreaAura() const { return m_isAreaAura; }
bool IsPeriodic() const { return m_isPeriodic; }
bool IsPassive() const { return m_isPassive; }
bool IsPersistent() const { return m_isPersistent; }
bool IsDeathPersistent() const { return m_isDeathPersist; }
bool IsRemovedOnShapeLost() const { return m_isRemovedOnShapeLost; }
bool IsInUse() const { return m_in_use;}
bool IsDeleted() const { return m_deleted;}
bool IsInUse() const { return m_in_use; }
bool IsDeleted() const { return m_deleted; }
void SetInUse(bool state)
{
@ -329,29 +424,26 @@ class MANGOS_DLL_SPEC Aura
void _AddAura();
bool _RemoveAura();
bool IsSingleTarget() {return m_isSingleTargetAura;}
void SetIsSingleTarget(bool val) { m_isSingleTargetAura = val;}
void SetRemoveMode(AuraRemoveMode mode) { m_removeMode = mode; }
virtual Unit* GetTriggerTarget() const { return m_target; }
virtual Unit* GetTriggerTarget() const { return m_spellAuraHolder->GetTarget(); }
// add/remove SPELL_AURA_MOD_SHAPESHIFT (36) linked auras
void HandleShapeshiftBoosts(bool apply);
void HandleSpellSpecificBoosts(bool apply);
// Allow Apply Aura Handler to modify and access m_AuraDRGroup
void setDiminishGroup(DiminishingGroup group) { m_AuraDRGroup = group; }
DiminishingGroup getDiminishGroup() const { return m_AuraDRGroup; }
void TriggerSpell();
void TriggerSpellWithValue();
uint32 const *getAuraSpellClassMask() const { return m_spellProto->GetEffectSpellClassMask(m_effIndex); }
uint32 const *getAuraSpellClassMask() const { return m_spellAuraHolder->GetSpellProto()->GetEffectSpellClassMask(m_effIndex); }
bool isAffectedOnSpell(SpellEntry const *spell) const;
bool isWeaponBuffCoexistableWith(Aura* ref);
//SpellAuraHolder const* GetHolder() const { return m_spellHolder; }
SpellAuraHolder* GetHolder() { return m_spellAuraHolder; }
SpellAuraHolder* const GetHolder() const { return m_spellAuraHolder; }
bool IsLastAuraOnHolder();
protected:
Aura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
Aura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
// must be called only from Aura::UpdateAura
virtual void Update(uint32 diff);
@ -366,10 +458,6 @@ class MANGOS_DLL_SPEC Aura
Modifier m_modifier;
SpellModifier *m_spellmod;
SpellEntry const *m_spellProto;
Unit* m_target;
uint64 m_caster_guid;
uint64 m_castItemGuid; // it is NOT safe to keep a pointer to the item because it may get deleted
time_t m_applyTime;
int32 m_currentBasePoints; // cache SpellEntry::CalculateSimpleValue and use for set custom base points
@ -380,27 +468,18 @@ class MANGOS_DLL_SPEC Aura
uint32 m_periodicTick; // Tick count pass (including current if use in tick code) from aura apply, used for some tick count dependent aura effects
AuraRemoveMode m_removeMode:8; // Store info for know remove aura reason
DiminishingGroup m_AuraDRGroup:8; // Diminishing
SpellEffectIndex m_effIndex :8; // Aura effect index in spell
uint8 m_auraSlot; // Aura slot on unit (for show in client)
uint8 m_auraFlags; // Aura info flag (for send data to client)
uint8 m_auraLevel; // Aura level (store caster level for correct show level dep amount)
uint8 m_procCharges; // Aura charges (0 for infinite)
uint8 m_stackAmount; // Aura stack amount
bool m_positive:1;
bool m_permanent:1;
bool m_isPeriodic:1;
bool m_isAreaAura:1;
bool m_isPassive:1;
bool m_isPersistent:1;
bool m_isDeathPersist:1;
bool m_isRemovedOnShapeLost:1;
bool m_deleted:1; // true if RemoveAura(iterator) called while in Aura::ApplyModifier call (added to Unit::m_deletedAuras)
bool m_isSingleTargetAura:1; // true if it's a single target spell and registered at caster - can change at spell steal for example
bool m_isPersistent:1;
uint32 m_in_use; // > 0 while in Aura::ApplyModifier call/Aura::Update/etc
SpellAuraHolder* const m_spellAuraHolder;
private:
void CleanupTriggeredSpells();
bool IsNeedVisibleSlot(Unit const* caster) const; // helper for check req. visibility slot
@ -410,7 +489,7 @@ class MANGOS_DLL_SPEC Aura
class MANGOS_DLL_SPEC AreaAura : public Aura
{
public:
AreaAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
AreaAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
~AreaAura();
protected:
void Update(uint32 diff);
@ -422,7 +501,7 @@ class MANGOS_DLL_SPEC AreaAura : public Aura
class MANGOS_DLL_SPEC PersistentAreaAura : public Aura
{
public:
PersistentAreaAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
PersistentAreaAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
~PersistentAreaAura();
protected:
void Update(uint32 diff);
@ -430,16 +509,17 @@ class MANGOS_DLL_SPEC PersistentAreaAura : public Aura
class MANGOS_DLL_SPEC SingleEnemyTargetAura : public Aura
{
friend Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, Unit *target, Unit *caster, Item* castItem);
friend Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster, Item* castItem);
public:
~SingleEnemyTargetAura();
Unit* GetTriggerTarget() const;
protected:
SingleEnemyTargetAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
SingleEnemyTargetAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
uint64 m_casters_target_guid;
};
Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
Aura* CreateAura(SpellEntry const* spellproto, SpellEffectIndex eff, int32 *currentBasePoints, SpellAuraHolder *holder, Unit *target, Unit *caster = NULL, Item* castItem = NULL);
SpellAuraHolder* CreateSpellAuraHolder(SpellEntry const* spellproto, Unit *target, WorldObject *caster, Item *castItem = NULL);
#endif

View file

@ -598,7 +598,7 @@ void Spell::EffectSchoolDMG(SpellEffectIndex effect_idx)
if (needConsume)
for (uint32 i = 0; i < doses; ++i)
unitTarget->RemoveSingleSpellAurasByCasterSpell(spellId, m_caster->GetGUID());
unitTarget->RemoveSingleAuraHolderFromStack(spellId, m_caster->GetGUID());
damage *= doses;
damage += int32(((Player*)m_caster)->GetTotalAttackPowerValue(BASE_ATTACK) * 0.09f * doses);
@ -2460,12 +2460,11 @@ void Spell::EffectDummy(SpellEffectIndex eff_idx)
else if (m_spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000010))
{
uint32 count = 0;
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
{
if (itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
itr->second->GetCasterGUID() == m_caster->GetGUID() &&
IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
itr->second->GetCasterGUID() == m_caster->GetGUID())
{
++count;
// max. 15%
@ -2635,8 +2634,8 @@ void Spell::EffectTriggerSpell(SpellEffectIndex effIndex)
// Cloak of Shadows
case 35729:
{
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
Unit::SpellAuraHolderMap& Auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::iterator iter = Auras.begin(); iter != Auras.end(); ++iter)
{
// Remove all harmful spells on you except positive/passive/physical auras
if (!iter->second->IsPositive() &&
@ -2972,16 +2971,16 @@ void Spell::EffectApplyAura(SpellEffectIndex eff_idx)
DEBUG_FILTER_LOG(LOG_FILTER_SPELL_CAST, "Spell: Aura is: %u", m_spellInfo->EffectApplyAuraName[eff_idx]);
Aura* Aur = CreateAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, caster, m_CastItem);
Aura* Aur = CreateAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], spellAuraHolder, unitTarget, caster, m_CastItem);
// Now Reduce spell duration using data received at spell hit
int32 duration = Aur->GetAuraMaxDuration();
int32 limitduration = GetDiminishingReturnsLimitDuration(m_diminishGroup,m_spellInfo);
unitTarget->ApplyDiminishingToDuration(m_diminishGroup, duration, m_caster, m_diminishLevel,limitduration);
Aur->setDiminishGroup(m_diminishGroup);
spellAuraHolder->setDiminishGroup(m_diminishGroup);
// if Aura removed and deleted, do not continue.
if(duration== 0 && !(Aur->IsPermanent()))
if(duration== 0 && !(spellAuraHolder->IsPermanent()))
{
delete Aur;
return;
@ -2993,7 +2992,7 @@ void Spell::EffectApplyAura(SpellEffectIndex eff_idx)
Aur->SetAuraDuration(duration);
}
unitTarget->AddAura(Aur);
spellAuraHolder->AddAura(Aur, eff_idx);
}
void Spell::EffectUnlearnSpecialization(SpellEffectIndex eff_idx)
@ -3200,7 +3199,7 @@ void Spell::EffectHeal(SpellEffectIndex /*eff_idx*/)
if (riptide)
{
addhealth += addhealth/4;
unitTarget->RemoveAura(riptide);
unitTarget->RemoveAurasDueToSpell(riptide->GetId());
}
}
}
@ -3506,8 +3505,8 @@ void Spell::EffectEnergize(SpellEffectIndex eff_idx)
{
// find elixirs on target
uint32 elixir_mask = 0;
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
Unit::SpellAuraHolderMap& Auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::iterator itr = Auras.begin(); itr != Auras.end(); ++itr)
{
uint32 spell_id = itr->second->GetId();
if(uint32 mask = sSpellMgr.GetSpellElixirMask(spell_id))
@ -3801,8 +3800,8 @@ void Spell::EffectApplyAreaAura(SpellEffectIndex eff_idx)
if (!unitTarget->isAlive())
return;
AreaAura* Aur = new AreaAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], unitTarget, m_caster, m_CastItem);
unitTarget->AddAura(Aur);
AreaAura* Aur = new AreaAura(m_spellInfo, eff_idx, &m_currentBasePoints[eff_idx], spellAuraHolder, unitTarget, m_caster, m_CastItem);
spellAuraHolder->AddAura(Aur, eff_idx);
}
void Spell::EffectSummonType(SpellEffectIndex eff_idx)
@ -4044,33 +4043,31 @@ void Spell::EffectDispel(SpellEffectIndex eff_idx)
return;
// Fill possible dispell list
std::vector <Aura *> dispel_list;
std::list <std::pair<SpellAuraHolder* ,uint32>> dispel_list;
// Create dispel mask by dispel type
uint32 dispel_type = m_spellInfo->EffectMiscValue[eff_idx];
uint32 dispelMask = GetDispellMask( DispelType(dispel_type) );
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
{
Aura *aur = (*itr).second;
if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
SpellAuraHolder *holder = itr->second;
if ((1<<holder->GetSpellProto()->Dispel) & dispelMask)
{
if(aur->GetSpellProto()->Dispel == DISPEL_MAGIC)
if(holder->GetSpellProto()->Dispel == DISPEL_MAGIC)
{
bool positive = true;
if (!aur->IsPositive())
if (!holder->IsPositive())
positive = false;
else
positive = (aur->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
positive = (holder->GetSpellProto()->AttributesEx & SPELL_ATTR_EX_NEGATIVE)==0;
// do not remove positive auras if friendly target
// negative auras if non-friendly target
if (positive == unitTarget->IsFriendlyTo(m_caster))
continue;
}
// Add aura to dispel list (all stack cases)
for(int k = 0; k < aur->GetStackAmount(); ++k)
dispel_list.push_back(aur);
dispel_list.push_back(std::pair<SpellAuraHolder* ,uint32>(holder, holder->GetStackAmount()));
}
}
// Ok if exist some buffs for dispel try dispel it
@ -4087,20 +4084,23 @@ void Spell::EffectDispel(SpellEffectIndex eff_idx)
for (int32 count=0; count < damage && !dispel_list.empty(); ++count)
{
// Random select buff for dispel
std::vector<Aura*>::iterator dispel_itr = dispel_list.begin();
std::list<std::pair<SpellAuraHolder* ,uint32>>::iterator dispel_itr = dispel_list.begin();
std::advance(dispel_itr,urand(0, dispel_list.size()-1));
Aura *aur = *dispel_itr;
SpellAuraHolder *holder = dispel_itr->first;
// remove entry from dispel_list
dispel_list.erase(dispel_itr);
dispel_itr->second -= 1;
SpellEntry const* spellInfo = aur->GetSpellProto();
// remove entry from dispel_list if nothing left in stack
if (dispel_itr->second == 0)
dispel_list.erase(dispel_itr);
SpellEntry const* spellInfo = holder->GetSpellProto();
// Base dispel chance
// TODO: possible chance depend from spell level??
int32 miss_chance = 0;
// Apply dispel mod from aura caster
if (Unit *caster = aur->GetCaster())
if (Unit *caster = holder->GetCaster())
{
if ( Player* modOwner = caster->GetSpellModOwner() )
modOwner->ApplySpellMod(spellInfo->Id, SPELLMOD_RESIST_DISPEL_CHANCE, miss_chance, this);
@ -4109,7 +4109,7 @@ void Spell::EffectDispel(SpellEffectIndex eff_idx)
if (roll_chance_i(miss_chance))
fail_list.push_back(spellInfo->Id);
else
success_list.push_back(std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
success_list.push_back(std::pair<uint32,uint64>(holder->GetId(),holder->GetCasterGUID()));
}
// Send success log and really remove auras
if (!success_list.empty())
@ -4126,7 +4126,7 @@ void Spell::EffectDispel(SpellEffectIndex eff_idx)
SpellEntry const* spellInfo = sSpellStore.LookupEntry(j->first);
data << uint32(spellInfo->Id); // Spell Id
data << uint8(0); // 0 - dispeled !=0 cleansed
unitTarget->RemoveSingleAuraDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
unitTarget->RemoveSingleAuraHolderDueToSpellByDispel(spellInfo->Id, j->second, m_caster);
}
m_caster->SendMessageToSet(&data, true);
@ -5002,16 +5002,16 @@ void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx)
{
uint32 stack = 0;
// Need refresh all Sunder Armor auras from this caster
Unit::AuraMap& suAuras = unitTarget->GetAuras();
Unit::SpellAuraHolderMap& suAuras = unitTarget->GetSpellAuraHolderMap();
SpellEntry const *spellInfo;
for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
for(Unit::SpellAuraHolderMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
{
spellInfo = (*itr).second->GetSpellProto();
if( spellInfo->SpellFamilyName == SPELLFAMILY_WARRIOR &&
(spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000004000)) &&
(*itr).second->GetCasterGUID() == m_caster->GetGUID())
{
(*itr).second->RefreshAura();
(*itr).second->RefreshHolder();
stack = (*itr).second->GetStackAmount();
break;
}
@ -5037,8 +5037,8 @@ void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx)
// full aura scan
else
{
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
{
if(itr->second->GetSpellProto()->Dispel == DISPEL_POISON)
{
@ -5125,12 +5125,11 @@ void Spell::EffectWeaponDmg(SpellEffectIndex eff_idx)
m_spellInfo->SpellIconID == 1736)
{
uint32 count = 0;
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr!=auras.end(); ++itr)
{
if(itr->second->GetSpellProto()->Dispel == DISPEL_DISEASE &&
itr->second->GetCasterGUID() == m_caster->GetGUID() &&
IsSpellLastAuraEffect(itr->second->GetSpellProto(), itr->second->GetEffIndex()))
itr->second->GetCasterGUID() == m_caster->GetGUID())
++count;
}
@ -5435,7 +5434,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
return;
}
case 24590: // Brittle Armor - need remove one 24575 Brittle Armor aura
unitTarget->RemoveSingleSpellAurasFromStack(24575);
unitTarget->RemoveSingleAuraHolderFromStack(24575);
return;
case 26275: // PX-238 Winter Wondervolt TRAP
{
@ -5454,7 +5453,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
return;
}
case 26465: // Mercurial Shield - need remove one 26464 Mercurial Shield aura
unitTarget->RemoveSingleSpellAurasFromStack(26464);
unitTarget->RemoveSingleAuraHolderFromStack(26464);
return;
case 25140: // Orb teleport spells
case 25143:
@ -6188,22 +6187,22 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
case 47422: // Everlasting Affliction
{
// Need refresh caster corruption auras on target
Unit::AuraMap& suAuras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
Unit::SpellAuraHolderMap& suAuras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::iterator itr = suAuras.begin(); itr != suAuras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if(spellInfo->SpellFamilyName == SPELLFAMILY_WARLOCK &&
(spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000000002)) &&
(*itr).second->GetCasterGUID() == m_caster->GetGUID())
(*itr).second->RefreshAura();
(*itr).second->RefreshHolder();
}
return;
}
case 63521: // Guarded by The Light (Paladin spell with SPELLFAMILY_WARLOCK)
{
// Divine Plea, refresh on target (3 aura slots)
if (Aura* aura = unitTarget->GetAura(54428, EFFECT_INDEX_0))
aura->RefreshAura();
if (SpellAuraHolder* holder = unitTarget->GetSpellAuraHolder(54428))
holder->RefreshHolder();
return;
}
@ -6220,15 +6219,15 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
return;
// Refresh Shadow Word: Pain on target
Unit::AuraMap& auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
Unit::SpellAuraHolderMap& auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::iterator itr = auras.begin(); itr != auras.end(); ++itr)
{
SpellEntry const *spellInfo = (*itr).second->GetSpellProto();
if (spellInfo->SpellFamilyName == SPELLFAMILY_PRIEST &&
(spellInfo->SpellFamilyFlags & UI64LIT(0x0000000000008000)) &&
(*itr).second->GetCasterGUID() == m_caster->GetGUID())
{
(*itr).second->RefreshAura();
(*itr).second->RefreshHolder();
return;
}
}
@ -6251,23 +6250,28 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
uint32 spellId = 0;
int32 basePoint = 0;
Unit* target = unitTarget;
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
Unit::SpellAuraHolderMap& Auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::iterator i = Auras.begin(); i != Auras.end(); ++i)
{
Aura *aura = (*i).second;
if (aura->GetCasterGUID() != m_caster->GetGUID())
SpellAuraHolder *holder = i->second;
if (holder->GetCasterGUID() != m_caster->GetGUID())
continue;
// Search only Serpent Sting, Viper Sting, Scorpid Sting auras
uint64 familyFlag = aura->GetSpellProto()->SpellFamilyFlags;
uint64 familyFlag = holder->GetSpellProto()->SpellFamilyFlags;
if (!(familyFlag & UI64LIT(0x000000800000C000)))
continue;
// Refresh aura duration
aura->RefreshAura();
holder->RefreshHolder();
Aura *aura = holder->GetAuraByEffectIndex(EFFECT_INDEX_0);
if (!aura)
continue;
// Serpent Sting - Instantly deals 40% of the damage done by your Serpent Sting.
if ((familyFlag & UI64LIT(0x0000000000004000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
if ((familyFlag & UI64LIT(0x0000000000004000)))
{
// m_amount already include RAP bonus
basePoint = aura->GetModifier()->m_amount * aura->GetAuraMaxTicks() * 40 / 100;
@ -6275,7 +6279,7 @@ void Spell::EffectScriptEffect(SpellEffectIndex eff_idx)
}
// Viper Sting - Instantly restores mana to you equal to 60% of the total amount drained by your Viper Sting.
if ((familyFlag & UI64LIT(0x0000008000000000)) && aura->GetEffIndex() == EFFECT_INDEX_0)
if ((familyFlag & UI64LIT(0x0000008000000000)))
{
uint32 target_max_mana = unitTarget->GetMaxPower(POWER_MANA);
if (!target_max_mana)
@ -7317,13 +7321,13 @@ void Spell::EffectDispelMechanic(SpellEffectIndex eff_idx)
uint32 mechanic = m_spellInfo->EffectMiscValue[eff_idx];
Unit::AuraMap& Auras = unitTarget->GetAuras();
for(Unit::AuraMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
Unit::SpellAuraHolderMap& Auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::iterator iter = Auras.begin(), next; iter != Auras.end(); iter = next)
{
next = iter;
++next;
SpellEntry const *spell = sSpellStore.LookupEntry(iter->second->GetSpellProto()->Id);
if(spell->Mechanic == mechanic || spell->EffectMechanic[iter->second->GetEffIndex()] == mechanic)
if(spell->Mechanic == mechanic || iter->second->HasAuraAndMechanicEffect(mechanic))
{
unitTarget->RemoveAurasDueToSpell(spell->Id);
if(Auras.empty())
@ -7661,19 +7665,19 @@ void Spell::EffectStealBeneficialBuff(SpellEffectIndex eff_idx)
if(!unitTarget || unitTarget==m_caster) // can't steal from self
return;
std::vector <Aura *> steal_list;
std::vector <SpellAuraHolder *> steal_list;
// Create dispel mask by dispel type
uint32 dispelMask = GetDispellMask( DispelType(m_spellInfo->EffectMiscValue[eff_idx]) );
Unit::AuraMap const& auras = unitTarget->GetAuras();
for(Unit::AuraMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
Unit::SpellAuraHolderMap const& auras = unitTarget->GetSpellAuraHolderMap();
for(Unit::SpellAuraHolderMap::const_iterator itr = auras.begin(); itr != auras.end(); ++itr)
{
Aura *aur = (*itr).second;
if (aur && (1<<aur->GetSpellProto()->Dispel) & dispelMask)
SpellAuraHolder *holder = itr->second;
if (holder && (1<<holder->GetSpellProto()->Dispel) & dispelMask)
{
// Need check for passive? this
if (aur->IsPositive() && !aur->IsPassive() && !(aur->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
steal_list.push_back(aur);
if (holder->IsPositive() && !holder->IsPassive() && !(holder->GetSpellProto()->AttributesEx4 & SPELL_ATTR_EX4_NOT_STEALABLE))
steal_list.push_back(holder);
}
}
// Ok if exist some buffs for dispel try dispel it
@ -7685,16 +7689,16 @@ void Spell::EffectStealBeneficialBuff(SpellEffectIndex eff_idx)
for (int32 count=0; count < damage && list_size > 0; ++count)
{
// Random select buff for dispel
Aura *aur = steal_list[urand(0, list_size-1)];
SpellAuraHolder *holder = steal_list[urand(0, list_size-1)];
// Not use chance for steal
// TODO possible need do it
success_list.push_back( std::pair<uint32,uint64>(aur->GetId(),aur->GetCasterGUID()));
success_list.push_back( std::pair<uint32,uint64>(holder->GetId(),holder->GetCasterGUID()));
// Remove buff from list for prevent doubles
for (std::vector<Aura *>::iterator j = steal_list.begin(); j != steal_list.end(); )
for (std::vector<SpellAuraHolder *>::iterator j = steal_list.begin(); j != steal_list.end(); )
{
Aura *stealed = *j;
if (stealed->GetId() == aur->GetId() && stealed->GetCasterGUID() == aur->GetCasterGUID())
SpellAuraHolder *stealed = *j;
if (stealed->GetId() == holder->GetId() && stealed->GetCasterGUID() == holder->GetCasterGUID())
{
j = steal_list.erase(j);
--list_size;

View file

@ -457,6 +457,12 @@ void WorldSession::HandleCancelAuraOpcode( WorldPacket& recvPacket)
return;
}
SpellAuraHolder *holder = _player->GetSpellAuraHolder(spellId);
// not own area auras can't be cancelled (note: maybe need to check for aura on holder and not general on spell)
if (holder && holder->GetCasterGUID() != _player->GetGUID() && HasAreaAuraEffect(holder->GetSpellProto()))
return;
// non channeled case
_player->RemoveAurasDueToSpellByCancel(spellId);
}

View file

@ -291,33 +291,46 @@ bool IsPassiveSpell(SpellEntry const *spellInfo)
return (spellInfo->Attributes & SPELL_ATTR_PASSIVE) != 0;
}
bool IsNoStackAuraDueToAura(uint32 spellId_1, SpellEffectIndex effIndex_1, uint32 spellId_2, SpellEffectIndex effIndex_2)
bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 spellId_2)
{
SpellEntry const *spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
SpellEntry const *spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
if(!spellInfo_1 || !spellInfo_2) return false;
if(spellInfo_1->Id == spellId_2) return false;
if (spellInfo_1->Effect[effIndex_1] != spellInfo_2->Effect[effIndex_2] ||
spellInfo_1->EffectItemType[effIndex_1] != spellInfo_2->EffectItemType[effIndex_2] ||
spellInfo_1->EffectMiscValue[effIndex_1] != spellInfo_2->EffectMiscValue[effIndex_2] ||
spellInfo_1->EffectApplyAuraName[effIndex_1] != spellInfo_2->EffectApplyAuraName[effIndex_2])
return false;
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
for (int32 j = 0; i < MAX_EFFECT_INDEX; ++j)
{
if (spellInfo_1->Effect[i] == spellInfo_2->Effect[j]
&& spellInfo_1->EffectApplyAuraName[i] == spellInfo_2->EffectApplyAuraName[j]
&& spellInfo_1->EffectMiscValue[i] == spellInfo_2->EffectMiscValue[j]
&& spellInfo_1->EffectItemType[i] == spellInfo_2->EffectItemType[j])
return true;
}
}
return true;
return false;
}
int32 CompareAuraRanks(uint32 spellId_1, SpellEffectIndex effIndex_1, uint32 spellId_2, SpellEffectIndex effIndex_2)
int32 CompareAuraRanks(uint32 spellId_1, uint32 spellId_2)
{
SpellEntry const*spellInfo_1 = sSpellStore.LookupEntry(spellId_1);
SpellEntry const*spellInfo_2 = sSpellStore.LookupEntry(spellId_2);
if(!spellInfo_1 || !spellInfo_2) return 0;
if (spellId_1 == spellId_2) return 0;
int32 diff = spellInfo_1->EffectBasePoints[effIndex_1] - spellInfo_2->EffectBasePoints[effIndex_2];
if (spellInfo_1->CalculateSimpleValue(effIndex_1) < 0 && spellInfo_2->CalculateSimpleValue(effIndex_2) < 0)
return -diff;
else return diff;
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if (spellInfo_1->Effect[i] != 0 && spellInfo_2->Effect[i] != 0 && spellInfo_1->Effect[i] == spellInfo_2->Effect[i])
{
int32 diff = spellInfo_1->EffectBasePoints[i] - spellInfo_2->EffectBasePoints[i];
if (spellInfo_1->CalculateSimpleValue(SpellEffectIndex(i)) < 0 && spellInfo_2->CalculateSimpleValue(SpellEffectIndex(i)) < 0)
return -diff;
else return diff;
}
}
return 0;
}
SpellSpecific GetSpellSpecific(uint32 spellId)
@ -1044,11 +1057,20 @@ struct DoSpellProcEvent
if (spe.spellFamilyName != r_spe.spellFamilyName)
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyName from first rank in chain", spell_id);
if (spe.spellFamilyMask != r_spe.spellFamilyMask)
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyMask from first rank in chain", spell_id);
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if (spe.spellFamilyMask[i] != r_spe.spellFamilyMask[i])
{
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyMask from first rank in chain", spell_id);
break;
}
if (spe.spellFamilyMask2 != r_spe.spellFamilyMask2)
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyMask2 from first rank in chain", spell_id);
if (spe.spellFamilyMask2[i] != r_spe.spellFamilyMask2[i])
{
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different spellFamilyMask2 from first rank in chain", spell_id);
break;
}
}
if (spe.procFlags != r_spe.procFlags)
sLog.outErrorDb("Spell %u listed in `spell_proc_event` as custom rank have different procFlags from first rank in chain", spell_id);
@ -1076,8 +1098,8 @@ void SpellMgr::LoadSpellProcEvents()
uint32 count = 0;
// 0 1 2 3 4 5 6 7 8 9 10
QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMask0, SpellFamilyMask1, SpellFamilyMask2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
// 0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
QueryResult *result = WorldDatabase.Query("SELECT entry, SchoolMask, SpellFamilyName, SpellFamilyMaskA0, SpellFamilyMaskA1, SpellFamilyMaskA2, SpellFamilyMaskB0, SpellFamilyMaskB1, SpellFamilyMaskB2, SpellFamilyMaskC0, SpellFamilyMaskC1, SpellFamilyMaskC2, procFlags, procEx, ppmRate, CustomChance, Cooldown FROM spell_proc_event");
if( !result )
{
barGoLink bar( 1 );
@ -1112,13 +1134,17 @@ void SpellMgr::LoadSpellProcEvents()
spe.schoolMask = fields[1].GetUInt32();
spe.spellFamilyName = fields[2].GetUInt32();
spe.spellFamilyMask = (uint64)fields[3].GetUInt32()|((uint64)fields[4].GetUInt32()<<32);
spe.spellFamilyMask2= fields[5].GetUInt32();
spe.procFlags = fields[6].GetUInt32();
spe.procEx = fields[7].GetUInt32();
spe.ppmRate = fields[8].GetFloat();
spe.customChance = fields[9].GetFloat();
spe.cooldown = fields[10].GetUInt32();
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
spe.spellFamilyMask[i] = (uint64)fields[i+3].GetUInt32()|((uint64)fields[i+6].GetUInt32()<<32);
spe.spellFamilyMask2[i] = fields[i+9].GetUInt32();
}
spe.procFlags = fields[12].GetUInt32();
spe.procEx = fields[13].GetUInt32();
spe.ppmRate = fields[14].GetFloat();
spe.customChance = fields[15].GetFloat();
spe.cooldown = fields[16].GetUInt32();
uint32 first_id = GetFirstSpellInChain(entry);
@ -1178,10 +1204,22 @@ void SpellMgr::LoadSpellProcEvents()
}
// totally redundant record
if (!spe.schoolMask && !spe.spellFamilyMask && !spe.spellFamilyMask2 && !spe.procFlags &&
if (!spe.schoolMask && !spe.procFlags &&
!spe.procEx && !spe.ppmRate && !spe.customChance && !spe.cooldown)
{
sLog.outErrorDb("Spell %u listed in `spell_proc_event` not have any useful data", entry);
bool empty = !spe.spellFamilyName ? true : false;
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if (spe.spellFamilyMask[i] || spe.spellFamilyMask2[i])
{
empty = false;
uint32 const* ptr = spell->GetEffectSpellClassMask(SpellEffectIndex(i));
if ((((uint64*)ptr)[0] != 0 && spe.spellFamilyMask[i] == ((uint64*)ptr)[0]) && (ptr[2] == 0 || spe.spellFamilyMask2[i] == ptr[2]))
sLog.outErrorDb("Spell %u listed in `spell_proc_event` have same class mask as in Spell.dbc (EffectIndex %u) and doesn't have any other data", entry, i);
}
}
if (empty)
sLog.outErrorDb("Spell %u listed in `spell_proc_event` not have any useful data", entry);
}
if (isCustom)
@ -1440,7 +1478,7 @@ void SpellMgr::LoadSpellBonuses()
sLog.outString( ">> Loaded %u extra spell bonus data", count);
}
bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active)
bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra)
{
// No extra req need
uint32 procEvent_procEx = PROC_EX_NONE;
@ -1474,32 +1512,20 @@ bool SpellMgr::IsSpellProcEventCanTriggeredBy(SpellProcEventEntry const * spellP
// Check (if set) for spellFamilyName
if(spellProcEvent->spellFamilyName && (spellProcEvent->spellFamilyName != procSpell->SpellFamilyName))
return false;
// spellFamilyName is Ok need check for spellFamilyMask if present
if(spellProcEvent->spellFamilyMask || spellProcEvent->spellFamilyMask2)
{
if ((spellProcEvent->spellFamilyMask & procSpell->SpellFamilyFlags ) == 0 &&
(spellProcEvent->spellFamilyMask2 & procSpell->SpellFamilyFlags2) == 0)
return false;
active = true; // Spell added manualy -> so its active spell
}
}
}
// Check for extra req (if none) and hit/crit
if (procEvent_procEx == PROC_EX_NONE)
{
// No extra req, so can trigger only for active (damage/healing present) and hit/crit
if((procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT)) && active)
// No extra req, so can trigger for (damage/healing present) and hit/crit
if(procExtra & (PROC_EX_NORMAL_HIT|PROC_EX_CRITICAL_HIT))
return true;
}
else // Passive spells hits here only if resist/reflect/immune/evade
else // all spells hits here only if resist/reflect/immune/evade
{
// Exist req for PROC_EX_EX_TRIGGER_ALWAYS
if (procEvent_procEx & PROC_EX_EX_TRIGGER_ALWAYS)
return true;
// Passive spells can`t trigger if need hit (exclude cases when procExtra include non-active flags)
if ((procEvent_procEx & PROC_EX_NORMAL_HIT & procExtra) && !active)
return false;
// Check Extra Requirement like (hit/crit/miss/resist/parry/dodge/block/immune/reflect/absorb and other)
if (procEvent_procEx & procExtra)
return true;

View file

@ -139,6 +139,28 @@ inline bool IsSpellHaveEffect(SpellEntry const *spellInfo, SpellEffects effect)
return false;
}
inline bool IsSpellAppliesAura(SpellEntry const *spellInfo, uint32 effectMask)
{
for(int i = 0; i < MAX_EFFECT_INDEX; ++i)
{
if (effectMask & (1 << i))
{
switch (spellInfo->Effect[i])
{
case SPELL_EFFECT_APPLY_AURA:
case SPELL_EFFECT_APPLY_AREA_AURA_PARTY:
case SPELL_EFFECT_APPLY_AREA_AURA_RAID:
case SPELL_EFFECT_APPLY_AREA_AURA_PET:
case SPELL_EFFECT_APPLY_AREA_AURA_FRIEND:
case SPELL_EFFECT_APPLY_AREA_AURA_ENEMY:
case SPELL_EFFECT_APPLY_AREA_AURA_OWNER:
return true;
}
}
}
return false;
}
inline bool IsEffectHandledOnDelayedSpellLaunch(SpellEntry const *spellInfo, SpellEffectIndex effecIdx)
{
switch (spellInfo->Effect[effecIdx])
@ -170,7 +192,7 @@ inline bool IsSpellLastAuraEffect(SpellEntry const *spellInfo, SpellEffectIndex
return true;
}
bool IsNoStackAuraDueToAura(uint32 spellId_1, SpellEffectIndex effIndex_1, uint32 spellId_2, SpellEffectIndex effIndex_2);
bool IsNoStackAuraDueToAura(uint32 spellId_1, uint32 spellId_2);
inline bool IsSealSpell(SpellEntry const *spellInfo)
{
@ -203,7 +225,7 @@ inline bool IsLootCraftingSpell(SpellEntry const *spellInfo)
(spellInfo->TotemCategory[0] != 0 || spellInfo->EffectItemType[0]==0)));
}
int32 CompareAuraRanks(uint32 spellId_1, SpellEffectIndex effIndex_1, uint32 spellId_2, SpellEffectIndex effIndex_2);
int32 CompareAuraRanks(uint32 spellId_1, uint32 spellId_2);
// order from less to more strict
bool IsSingleFromSpellSpecificPerTargetPerCaster(SpellSpecific spellSpec1,SpellSpecific spellSpec2);
@ -390,6 +412,30 @@ inline bool IsAreaAuraEffect(uint32 effect)
return false;
}
inline bool HasAreaAuraEffect(SpellEntry const *spellInfo)
{
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
if (IsAreaAuraEffect(spellInfo->Effect[i]))
return true;
return false;
}
inline bool HasAuraWithTriggerEffect(SpellEntry const *spellInfo)
{
for (int32 i = 0; i < MAX_EFFECT_INDEX; ++i)
{
switch(spellInfo->Effect[i])
{
case SPELL_AURA_PERIODIC_TRIGGER_SPELL:
case SPELL_AURA_PROC_TRIGGER_SPELL:
case SPELL_AURA_PROC_TRIGGER_DAMAGE:
case SPELL_AURA_PROC_TRIGGER_SPELL_WITH_VALUE:
return true;
}
}
return false;
}
inline bool IsDispelSpell(SpellEntry const *spellInfo)
{
return IsSpellHaveEffect(spellInfo, SPELL_EFFECT_DISPEL);
@ -553,8 +599,8 @@ struct SpellProcEventEntry
{
uint32 schoolMask; // if nonzero - bit mask for matching proc condition based on spell candidate's school: Fire=2, Mask=1<<(2-1)=2
uint32 spellFamilyName; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyNamer value
uint64 spellFamilyMask; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do)
uint32 spellFamilyMask2; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags2 (like auras 107 and 108 do)
uint64 spellFamilyMask[MAX_EFFECT_INDEX]; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags (like auras 107 and 108 do)
uint32 spellFamilyMask2[MAX_EFFECT_INDEX]; // if nonzero - for matching proc condition based on candidate spell's SpellFamilyFlags2 (like auras 107 and 108 do)
uint32 procFlags; // bitmask for matching proc event
uint32 procEx; // proc Extend info (see ProcFlagsEx)
float ppmRate; // for melee (ranged?) damage spells - proc rate per minute. if zero, falls back to flat chance from Spell.dbc
@ -831,7 +877,7 @@ class SpellMgr
return itr->second;
}
static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra, bool active);
static bool IsSpellProcEventCanTriggeredBy( SpellProcEventEntry const * spellProcEvent, uint32 EventProcFlag, SpellEntry const * procSpell, uint32 procFlags, uint32 procExtra);
// Spell bonus data
SpellBonusEntry const* GetSpellBonusData(uint32 spellId) const

File diff suppressed because it is too large Load diff

View file

@ -294,6 +294,7 @@ struct SpellEntry;
struct SpellEntryExt;
class Aura;
class SpellAuraHolder;
class Creature;
class Spell;
class DynamicObject;
@ -931,6 +932,9 @@ struct SpellPeriodicAuraLogInfo
uint32 createProcExtendMask(SpellNonMeleeDamage *damageInfo, SpellMissInfo missCondition);
typedef bool(Unit::*pAuraProcHandler)(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
extern pAuraProcHandler AuraProcHandler[TOTAL_AURAS];
#define MAX_DECLINED_NAME_CASES 5
struct DeclinedName
@ -1096,8 +1100,9 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
{
public:
typedef std::set<Unit*> AttackerSet;
typedef std::pair<uint32, SpellEffectIndex> spellEffectPair;
typedef std::multimap< spellEffectPair, Aura*> AuraMap;
typedef std::multimap< uint32, SpellAuraHolder*> SpellAuraHolderMap;
typedef std::pair<SpellAuraHolderMap::iterator, SpellAuraHolderMap::iterator> SpellAuraHolderBounds;
typedef std::list<SpellAuraHolder *> SpellAuraHolderList;
typedef std::list<Aura *> AuraList;
typedef std::list<DiminishingReturn> Diminishing;
typedef std::set<uint32> ComboPointHolderSet;
@ -1348,12 +1353,17 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void ClearInCombat();
uint32 GetCombatTimer() const { return m_CombatTimer; }
bool HasAuraType(AuraType auraType) const;
bool HasAura(uint32 spellId, SpellEffectIndex effIndex) const
SpellAuraHolderBounds GetSpellAuraHolderBounds(uint32 spell_id)
{
return m_Auras.find(spellEffectPair(spellId, effIndex)) != m_Auras.end();
return SpellAuraHolderBounds(m_spellAuraHolders.lower_bound(spell_id), m_spellAuraHolders.upper_bound(spell_id));
}
bool HasAuraType(AuraType auraType) const;
bool HasAura(uint32 spellId, SpellEffectIndex effIndex) const;
bool HasAura(uint32 spellId) const
{
return m_spellAuraHolders.find(spellId) != m_spellAuraHolders.end();
}
bool HasAura(uint32 spellId) const;
bool virtual HasSpell(uint32 /*spellID*/) const { return false; }
@ -1493,18 +1503,19 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
template<typename Func>
bool CheckAllControlledUnits(Func const& func, bool withTotems, bool withGuardians, bool withCharms) const;
bool AddAura(Aura *aur);
bool AddSpellAuraHolder(SpellAuraHolder *holder);
// removing specific aura stack
void RemoveAura(Aura* aura, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(uint32 spellId, SpellEffectIndex effindex, Aura* except = NULL, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAura(uint32 spellId, SpellEffectIndex effindex, Aura* except = NULL);
void RemoveSpellAuraHolder(SpellAuraHolder *holder, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraFromSpellAuraHolder(SpellAuraHolder *holder, SpellEffectIndex index, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraFromSpellAuraHolder(uint32 id, SpellEffectIndex index, uint64 casterGUID, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
// removing specific aura stacks by diff reasons and selections
void RemoveAurasDueToSpell(uint32 spellId, Aura* except = NULL, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAurasDueToSpell(uint32 spellId, SpellAuraHolder* except = NULL, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveAurasDueToItemSpell(Item* castItem,uint32 spellId);
void RemoveAurasByCasterSpell(uint32 spellId, uint64 casterGUID);
void RemoveAurasByCasterSpell(uint32 spellId, SpellEffectIndex effindex, uint64 casterGUID);
void RemoveAurasDueToSpellBySteal(uint32 spellId, uint64 casterGUID, Unit *stealer);
void RemoveAurasDueToSpellByCancel(uint32 spellId);
@ -1513,24 +1524,18 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
void RemoveAurasAtMechanicImmunity(uint32 mechMask, uint32 exceptSpellId, bool non_positive = false);
void RemoveSpellsCausingAura(AuraType auraType);
void RemoveRankAurasDueToSpell(uint32 spellId);
bool RemoveNoStackAurasDueToAura(Aura *Aur);
bool RemoveNoStackAurasDueToAuraHolder(SpellAuraHolder *holder);
void RemoveAurasWithInterruptFlags(uint32 flags);
void RemoveAurasWithDispelType( DispelType type );
void RemoveAllAuras(AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveArenaAuras(bool onleave = false);
void RemoveAllAurasOnDeath();
// removing specific aura FROM stack
void RemoveSingleAuraFromStack(uint32 spellId, SpellEffectIndex effindex, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraFromStack(AuraMap::iterator &i, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
// removing specific aura FROM stack by diff reasons and selections
void RemoveSingleSpellAurasFromStack(uint32 spellId, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleSpellAurasByCasterSpell(uint32 spellId, uint64 casterGUID, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraByCasterSpell(uint32 spellId, SpellEffectIndex effindex, uint64 casterGUID, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler);
void RemoveSingleAuraHolderFromStack(uint32 spellId, uint64 casterGUID = 0, AuraRemoveMode mode = AURA_REMOVE_BY_DEFAULT);
void RemoveSingleAuraHolderDueToSpellByDispel(uint32 spellId, uint64 casterGUID, Unit *dispeler);
void DelayAura(uint32 spellId, SpellEffectIndex effindex, int32 delaytime);
void DelaySpellAuraHolder(uint32 spellId, int32 delaytime);
float GetResistanceBuffMods(SpellSchools school, bool positive) const { return GetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school ); }
void SetResistanceBuffMods(SpellSchools school, bool positive, float val) { SetFloatValue(positive ? UNIT_FIELD_RESISTANCEBUFFMODSPOSITIVE+school : UNIT_FIELD_RESISTANCEBUFFMODSNEGATIVE+school,val); }
@ -1639,8 +1644,8 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
virtual bool IsVisibleInGridForPlayer(Player* pl) const = 0;
bool isInvisibleForAlive() const;
AuraList & GetSingleCastAuras() { return m_scAuras; }
AuraList const& GetSingleCastAuras() const { return m_scAuras; }
SpellAuraHolderList & GetSingleCastSpellAuraHolders() { return m_scSpellAuraHolders; }
SpellAuraHolderList const& GetSingleCastSpellAuraHolders() const { return m_scSpellAuraHolders; }
SpellImmuneList m_spellImmune[MAX_SPELL_IMMUNITY];
// Threat related methods
@ -1676,9 +1681,10 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
Aura* GetAura(uint32 spellId, SpellEffectIndex effindex);
Aura* GetAura(AuraType type, uint32 family, uint64 familyFlag, uint32 familyFlag2 = 0, uint64 casterGUID = 0);
SpellAuraHolder* GetSpellAuraHolder (uint32 spellid, uint64 casterGUID = 0);
AuraMap & GetAuras() { return m_Auras; }
AuraMap const& GetAuras() const { return m_Auras; }
SpellAuraHolderMap & GetSpellAuraHolderMap() { return m_spellAuraHolders; }
SpellAuraHolderMap const& GetSpellAuraHolderMap() const { return m_spellAuraHolders; }
AuraList const& GetAurasByType(AuraType type) const { return m_modAuras[type]; }
void ApplyAuraProcTriggerDamage(Aura* aura, bool apply);
@ -1752,6 +1758,34 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
uint32 SpellCriticalDamageBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);
uint32 SpellCriticalHealingBonus(SpellEntry const *spellProto, uint32 damage, Unit *pVictim);
bool IsTriggeredAtSpellProcEvent(Unit *pVictim, SpellAuraHolder* holder, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, SpellProcEventEntry const*& spellProcEvent );
// Aura proc handlers
bool HandleDummyAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleHasteAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleSpellCritChanceAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleProcTriggerSpellAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleProcTriggerDamageAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleMendingAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleModCastingSpeedNotStackAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleReflectSpellsSchoolAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleModPowerCostSchoolAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleMechanicImmuneResistanceAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleModDamageFromCasterAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleMaelstromWeaponAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleAddPctModifierAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleModDamagePercentDoneAuraProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleNULLProc(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
// no proc handler for this aura type
return true;
}
bool HandleCantTrigger(Unit *pVictim, uint32 damage, Aura* triggeredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown)
{
// this aura type can't proc
return false;
}
void SetLastManaUse()
{
if (GetTypeId() == TYPEID_PLAYER && !IsUnderLastManaUseEffect())
@ -1856,11 +1890,12 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
DeathState m_deathState;
AuraMap m_Auras;
AuraMap::iterator m_AurasUpdateIterator; // != end() in Unit::m_Auras update and point to next element
AuraList m_deletedAuras; // auras removed while in ApplyModifier and waiting deleted
SpellAuraHolderMap m_spellAuraHolders;
SpellAuraHolderMap::iterator m_spellAuraHoldersUpdateIterator; // != end() in Unit::m_spellAuraHolders update and point to next element
AuraList m_deletedAuras; // auras removed while in ApplyModifier and waiting deleted
SpellAuraHolderList m_deletedHolders;
AuraList m_scAuras; // casted by unit single per-caster auras
SpellAuraHolderList m_scSpellAuraHolders; // casted by unit single per-caster auras
typedef std::list<uint64> DynObjectGUIDs;
DynObjectGUIDs m_dynObjGUIDs;
@ -1892,14 +1927,6 @@ class MANGOS_DLL_SPEC Unit : public WorldObject
private:
void CleanupDeletedAuras();
bool IsTriggeredAtSpellProcEvent(Unit *pVictim, Aura* aura, SpellEntry const* procSpell, uint32 procFlag, uint32 procExtra, WeaponAttackType attType, bool isVictim, bool active, SpellProcEventEntry const*& spellProcEvent );
bool HandleDummyAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleHasteAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleSpellCritChanceAuraProc( Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleProcTriggerSpell(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 procFlag, uint32 procEx, uint32 cooldown);
bool HandleOverrideClassScriptAuraProc(Unit *pVictim, uint32 damage, Aura* triggredByAura, SpellEntry const *procSpell, uint32 cooldown);
bool HandleMendingAuraProc(Aura* triggeredByAura);
// player or player's pet
float GetCombatRatingReduction(CombatRating cr) const;
uint32 GetCombatRatingDamageReduction(CombatRating cr, float rate, float cap, uint32 damage) const;

File diff suppressed because it is too large Load diff

View file

@ -1,4 +1,4 @@
#ifndef __REVISION_NR_H__
#define __REVISION_NR_H__
#define REVISION_NR "10155"
#define REVISION_NR "10156"
#endif // __REVISION_NR_H__

View file

@ -1,6 +1,6 @@
#ifndef __REVISION_SQL_H__
#define __REVISION_SQL_H__
#define REVISION_DB_CHARACTERS "required_10051_01_characters_character_aura"
#define REVISION_DB_MANGOS "required_10148_01_mangos_mangos_string"
#define REVISION_DB_CHARACTERS "required_10156_02_characters_pet_aura"
#define REVISION_DB_MANGOS "required_10156_03_mangos_spell_proc_event"
#define REVISION_DB_REALMD "required_10008_01_realmd_realmd_db_version"
#endif // __REVISION_SQL_H__