diff --git a/src/game/SharedDefines.h b/src/game/SharedDefines.h index 95b46ff0a..d74fc1943 100644 --- a/src/game/SharedDefines.h +++ b/src/game/SharedDefines.h @@ -329,7 +329,7 @@ const uint32 ItemQualityColors[MAX_ITEM_QUALITY] = { #define SPELL_ATTR_EX3_UNK9 0x00000200 // 9 #define SPELL_ATTR_EX3_MAIN_HAND 0x00000400 // 10 Main hand weapon required #define SPELL_ATTR_EX3_BATTLEGROUND 0x00000800 // 11 Can casted only on battleground -#define SPELL_ATTR_EX3_UNK12 0x00001000 // 12 +#define SPELL_ATTR_EX3_CAST_ON_DEAD 0x00001000 // 12 target is a dead player (not every spell has this flag) #define SPELL_ATTR_EX3_UNK13 0x00002000 // 13 #define SPELL_ATTR_EX3_UNK14 0x00004000 // 14 "Honorless Target" only this spells have this flag #define SPELL_ATTR_EX3_UNK15 0x00008000 // 15 Auto Shoot, Shoot, Throw, - this is autoshot flag diff --git a/src/game/Spell.cpp b/src/game/Spell.cpp index 2c96a659b..44716ada0 100644 --- a/src/game/Spell.cpp +++ b/src/game/Spell.cpp @@ -1210,7 +1210,7 @@ bool Spell::IsAliveUnitPresentInTargetList() { Unit *unit = m_caster->GetGUID() == ihit->targetGUID ? m_caster : ObjectAccessor::GetUnit(*m_caster, ihit->targetGUID); - if (unit && unit->isAlive()) + if (unit && (unit->isAlive() ^ IsDeathOnlySpell(m_spellInfo))) needAliveTargetMask &= ~ihit->effectMask; // remove from need alive mask effect that have alive target } } @@ -3875,6 +3875,9 @@ SpellCastResult Spell::CheckCast(bool strict) return SPELL_FAILED_NOT_READY; } + if (IsDeathOnlySpell(m_spellInfo) && m_caster->isAlive()) + return SPELL_FAILED_TARGET_NOT_DEAD; + // only allow triggered spells if at an ended battleground if( !m_IsTriggeredSpell && m_caster->GetTypeId() == TYPEID_PLAYER) if(BattleGround * bg = ((Player*)m_caster)->GetBattleGround()) diff --git a/src/game/Spell.h b/src/game/Spell.h index d345aef13..ca60136f7 100644 --- a/src/game/Spell.h +++ b/src/game/Spell.h @@ -657,7 +657,9 @@ namespace MaNGOS for(typename GridRefManager::iterator itr = m.begin(); itr != m.end(); ++itr) { - if ( !itr->getSource()->isTargetableForAttack() + // there are still more spells which can be casted on dead, but + // they are no AOE and don't have such a nice SPELL_ATTR flag + if ( !itr->getSource()->isTargetableForAttack(i_spell.m_spellInfo->AttributesEx3 & SPELL_ATTR_EX3_CAST_ON_DEAD) // mostly phase check || !itr->getSource()->IsInMap(i_originalCaster)) continue; diff --git a/src/game/SpellAuras.cpp b/src/game/SpellAuras.cpp index ff6d7917a..aec5b58d7 100644 --- a/src/game/SpellAuras.cpp +++ b/src/game/SpellAuras.cpp @@ -6267,7 +6267,7 @@ void Aura::HandleSchoolAbsorb(bool apply, bool Real) void Aura::PeriodicTick() { - if(!m_target->isAlive()) + if (!m_target->isAlive() ^ IsDeathOnlySpell(GetSpellProto())) return; switch(m_modifier.m_auraname) diff --git a/src/game/SpellEffects.cpp b/src/game/SpellEffects.cpp index be7318945..9cc895c41 100644 --- a/src/game/SpellEffects.cpp +++ b/src/game/SpellEffects.cpp @@ -2427,8 +2427,8 @@ void Spell::EffectApplyAura(uint32 i) return; // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) - if( !unitTarget->isAlive() && !IsDeathPersistentSpell(m_spellInfo) && - (unitTarget->GetTypeId()!=TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) + if ( (!unitTarget->isAlive() && !(IsDeathOnlySpell(m_spellInfo) || IsDeathPersistentSpell(m_spellInfo))) && + (unitTarget->GetTypeId() != TYPEID_PLAYER || !((Player*)unitTarget)->GetSession()->PlayerLoading()) ) return; Unit* caster = m_originalCaster ? m_originalCaster : m_caster; diff --git a/src/game/SpellMgr.h b/src/game/SpellMgr.h index 45bc53d41..236a7f833 100644 --- a/src/game/SpellMgr.h +++ b/src/game/SpellMgr.h @@ -198,6 +198,12 @@ inline bool IsPassiveSpellStackableWithRanks(SpellEntry const* spellProto) return !IsSpellHaveEffect(spellProto,SPELL_EFFECT_APPLY_AURA); } +inline bool IsDeathOnlySpell(SpellEntry const *spellInfo) +{ + return spellInfo->AttributesEx & SPELL_ATTR_EX3_CAST_ON_DEAD + || spellInfo->Id == 2584 + || spellInfo->Id == 22011; +} inline bool IsDeathPersistentSpell(SpellEntry const *spellInfo) { diff --git a/src/game/Unit.cpp b/src/game/Unit.cpp index 141e8b68f..7d30ae55f 100644 --- a/src/game/Unit.cpp +++ b/src/game/Unit.cpp @@ -3403,7 +3403,7 @@ bool Unit::AddAura(Aura *Aur) // ghost spell check, allow apply any auras at player loading in ghost mode (will be cleanup after load) if( !isAlive() && !IsDeathPersistentSpell(aurSpellInfo) && - Aur->GetId() != 2584 && // Waiting to Resurrect (not have death persistence flag) + !IsDeathOnlySpell(aurSpellInfo) && (GetTypeId()!=TYPEID_PLAYER || !((Player*)this)->GetSession()->PlayerLoading()) ) { delete Aur; @@ -9385,7 +9385,7 @@ void Unit::ClearInCombat() ((Player*)this)->UpdatePotionCooldown(); } -bool Unit::isTargetableForAttack() const +bool Unit::isTargetableForAttack(bool inverseAlive /*=false*/) const { if (GetTypeId()==TYPEID_PLAYER && ((Player *)this)->isGameMaster()) return false; @@ -9397,7 +9397,10 @@ bool Unit::isTargetableForAttack() const if (HasFlag(UNIT_FIELD_FLAGS, UNIT_FLAG_OOC_NOT_ATTACKABLE)) return false; - return IsInWorld() && isAlive() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; + if (!(isAlive() ^ inverseAlive)) + return false; + + return IsInWorld() && !hasUnitState(UNIT_STAT_DIED)&& !isInFlight() /*&& !isStealth()*/; } int32 Unit::ModifyHealth(int32 dVal) diff --git a/src/game/Unit.h b/src/game/Unit.h index b098d4dc9..5903ba3b9 100644 --- a/src/game/Unit.h +++ b/src/game/Unit.h @@ -1110,7 +1110,7 @@ class MANGOS_DLL_SPEC Unit : public WorldObject void RemoveSpellbyDamageTaken(AuraType auraType, uint32 damage); - bool isTargetableForAttack() const; + bool isTargetableForAttack(bool inversAlive = false) const; virtual bool IsInWater() const; virtual bool IsUnderWater() const; bool isInAccessablePlaceFor(Creature const* c) const; diff --git a/src/shared/revision_nr.h b/src/shared/revision_nr.h index 492bca4fe..93ff03c0a 100644 --- a/src/shared/revision_nr.h +++ b/src/shared/revision_nr.h @@ -1,4 +1,4 @@ #ifndef __REVISION_NR_H__ #define __REVISION_NR_H__ - #define REVISION_NR "8551" + #define REVISION_NR "8552" #endif // __REVISION_NR_H__