Core/Spells: Implement SPELL_ATTR4_PROC_ONLY_ON_CASTER properly. Closes #5204

This commit is contained in:
Liberate
2012-04-05 20:09:20 +02:00
parent 6759bcab16
commit 926f02f792
3 changed files with 29 additions and 17 deletions
@@ -411,7 +411,7 @@ enum SpellAttr3
enum SpellAttr4 enum SpellAttr4
{ {
SPELL_ATTR4_UNK0 = 0x00000001, // 0 SPELL_ATTR4_UNK0 = 0x00000001, // 0
SPELL_ATTR4_PROC_ONLY_ON_DUMMY = 0x00000002, // 1 proc only on SPELL_EFFECT_DUMMY? SPELL_ATTR4_PROC_ONLY_ON_CASTER = 0x00000002, // 1 proc only on effects with TARGET_UNIT_CASTER?
SPELL_ATTR4_UNK2 = 0x00000004, // 2 SPELL_ATTR4_UNK2 = 0x00000004, // 2
SPELL_ATTR4_UNK3 = 0x00000008, // 3 SPELL_ATTR4_UNK3 = 0x00000008, // 3
SPELL_ATTR4_UNK4 = 0x00000010, // 4 This will no longer cause guards to attack on use?? SPELL_ATTR4_UNK4 = 0x00000010, // 4 This will no longer cause guards to attack on use??
+17 -13
View File
@@ -2745,18 +2745,18 @@ void Spell::DoTriggersOnSpellHit(Unit* unit, uint8 effMask)
if (!m_hitTriggerSpells.empty()) if (!m_hitTriggerSpells.empty())
{ {
int _duration = 0; int _duration = 0;
for (HitTriggerSpells::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i) for (HitTriggerSpellList::const_iterator i = m_hitTriggerSpells.begin(); i != m_hitTriggerSpells.end(); ++i)
{ {
if (CanExecuteTriggersOnHit(effMask, i->first) && roll_chance_i(i->second)) if (CanExecuteTriggersOnHit(effMask, i->triggeredByAura) && roll_chance_i(i->chance))
{ {
m_caster->CastSpell(unit, i->first, true); m_caster->CastSpell(unit, i->triggeredSpell, true);
sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->first->Id); sLog->outDebug(LOG_FILTER_SPELLS_AURAS, "Spell %d triggered spell %d by SPELL_AURA_ADD_TARGET_TRIGGER aura", m_spellInfo->Id, i->triggeredSpell->Id);
// SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration // SPELL_AURA_ADD_TARGET_TRIGGER auras shouldn't trigger auras without duration
// set duration of current aura to the triggered spell // set duration of current aura to the triggered spell
if (i->first->GetDuration() == -1) if (i->triggeredSpell->GetDuration() == -1)
{ {
if (Aura* triggeredAur = unit->GetAura(i->first->Id, m_caster->GetGUID())) if (Aura* triggeredAur = unit->GetAura(i->triggeredSpell->Id, m_caster->GetGUID()))
{ {
// get duration from aura-only once // get duration from aura-only once
if (!_duration) if (!_duration)
@@ -7171,14 +7171,13 @@ void Spell::CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTarget
} }
} }
bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* spellInfo) const bool Spell::CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura) const
{ {
bool only_on_dummy = (spellInfo && (spellInfo->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_DUMMY)); bool only_on_caster = (triggeredByAura && (triggeredByAura->AttributesEx4 & SPELL_ATTR4_PROC_ONLY_ON_CASTER));
// If triggered spell has SPELL_ATTR4_PROC_ONLY_ON_DUMMY then it can only proc on a casted spell with SPELL_EFFECT_DUMMY // If triggeredByAura has SPELL_ATTR4_PROC_ONLY_ON_CASTER then it can only proc on a casted spell with TARGET_UNIT_CASTER
// If triggered spell doesn't have SPELL_ATTR4_PROC_ONLY_ON_DUMMY then it can NOT proc on SPELL_EFFECT_DUMMY (needs confirmation)
for (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i) for (uint8 i = 0;i < MAX_SPELL_EFFECTS; ++i)
{ {
if ((effMask & (1 << i)) && (only_on_dummy == (m_spellInfo->Effects[i].Effect == SPELL_EFFECT_DUMMY))) if ((effMask & (1 << i)) && (!only_on_caster || (m_spellInfo->Effects[i].TargetA.GetTarget() == TARGET_UNIT_CASTER)))
return true; return true;
} }
return false; return false;
@@ -7230,9 +7229,14 @@ void Spell::PrepareTriggersExecutedOnHit()
// calculate the chance using spell base amount, because aura amount is not updated on combo-points change // calculate the chance using spell base amount, because aura amount is not updated on combo-points change
// this possibly needs fixing // this possibly needs fixing
int32 auraBaseAmount = (*i)->GetBaseAmount(); int32 auraBaseAmount = (*i)->GetBaseAmount();
int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
// proc chance is stored in effect amount // proc chance is stored in effect amount
m_hitTriggerSpells.push_back(std::make_pair(spellInfo, chance * (*i)->GetBase()->GetStackAmount())); int32 chance = m_caster->CalculateSpellDamage(NULL, auraSpellInfo, auraSpellIdx, &auraBaseAmount);
// build trigger and add to the list
HitTriggerSpell spellTriggerInfo;
spellTriggerInfo.triggeredSpell = spellInfo;
spellTriggerInfo.triggeredByAura = auraSpellInfo;
spellTriggerInfo.chance = chance * (*i)->GetBase()->GetStackAmount();
m_hitTriggerSpells.push_back(spellTriggerInfo);
} }
} }
} }
+11 -3
View File
@@ -633,10 +633,18 @@ class Spell
void CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTargets, SpellEffIndex effIndex); void CallScriptAfterUnitTargetSelectHandlers(std::list<Unit*>& unitTargets, SpellEffIndex effIndex);
std::list<SpellScript*> m_loadedScripts; std::list<SpellScript*> m_loadedScripts;
bool CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* spellInfo = NULL) const; struct HitTriggerSpell
{
SpellInfo const* triggeredSpell;
SpellInfo const* triggeredByAura;
// uint8 triggeredByEffIdx This might be needed at a later stage - No need known for now
int32 chance;
};
bool CanExecuteTriggersOnHit(uint8 effMask, SpellInfo const* triggeredByAura = NULL) const;
void PrepareTriggersExecutedOnHit(); void PrepareTriggersExecutedOnHit();
typedef std::list< std::pair<SpellInfo const*, int32> > HitTriggerSpells; typedef std::list<HitTriggerSpell> HitTriggerSpellList;
HitTriggerSpells m_hitTriggerSpells; HitTriggerSpellList m_hitTriggerSpells;
// effect helpers // effect helpers
void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons); void SummonGuardian(uint32 i, uint32 entry, SummonPropertiesEntry const* properties, uint32 numSummons);